lingo.dev 0.78.17 → 0.79.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.
package/build/cli.cjs CHANGED
@@ -620,9 +620,9 @@ function makeGitlabInitializer(spinner) {
620
620
 
621
621
  // src/cli/cmd/init.ts
622
622
 
623
- var openUrl = (path14) => {
623
+ var openUrl = (path15) => {
624
624
  const settings = getSettings(void 0);
625
- _open2.default.call(void 0, `${settings.auth.webUrl}${path14}`, { wait: false });
625
+ _open2.default.call(void 0, `${settings.auth.webUrl}${path15}`, { wait: false });
626
626
  };
627
627
  var throwHelpError = (option, value) => {
628
628
  if (value === "help") {
@@ -962,8 +962,8 @@ var files_default = new (0, _interactivecommander.Command)().command("files").de
962
962
  } else if (type.target) {
963
963
  result.push(...targetPaths);
964
964
  }
965
- result.forEach((path14) => {
966
- console.log(path14);
965
+ result.forEach((path15) => {
966
+ console.log(path15);
967
967
  });
968
968
  }
969
969
  }
@@ -1531,9 +1531,9 @@ function createHtmlLoader() {
1531
1531
  const bDepth = b.split("/").length;
1532
1532
  return aDepth - bDepth;
1533
1533
  });
1534
- paths.forEach((path14) => {
1535
- const value = data[path14];
1536
- const [nodePath, attribute] = path14.split("#");
1534
+ paths.forEach((path15) => {
1535
+ const value = data[path15];
1536
+ const [nodePath, attribute] = path15.split("#");
1537
1537
  const [rootTag, ...indices] = nodePath.split("/");
1538
1538
  let parent = rootTag === "head" ? document.head : document.body;
1539
1539
  let current = parent;
@@ -2597,18 +2597,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2597
2597
  }
2598
2598
  function serializeStructuredText(rawStructuredText) {
2599
2599
  return serializeStructuredTextNode(rawStructuredText);
2600
- function serializeStructuredTextNode(node, path14 = [], acc = {}) {
2600
+ function serializeStructuredTextNode(node, path15 = [], acc = {}) {
2601
2601
  if ("document" in node) {
2602
- return serializeStructuredTextNode(node.document, [...path14, "document"], acc);
2602
+ return serializeStructuredTextNode(node.document, [...path15, "document"], acc);
2603
2603
  }
2604
2604
  if (!_lodash2.default.isNil(node.value)) {
2605
- acc[[...path14, "value"].join(".")] = node.value;
2605
+ acc[[...path15, "value"].join(".")] = node.value;
2606
2606
  } else if (_lodash2.default.get(node, "type") === "block") {
2607
- acc[[...path14, "item"].join(".")] = serializeBlock(node.item);
2607
+ acc[[...path15, "item"].join(".")] = serializeBlock(node.item);
2608
2608
  }
2609
2609
  if (node.children) {
2610
2610
  for (let i = 0; i < node.children.length; i++) {
2611
- serializeStructuredTextNode(node.children[i], [...path14, i.toString()], acc);
2611
+ serializeStructuredTextNode(node.children[i], [...path15, i.toString()], acc);
2612
2612
  }
2613
2613
  }
2614
2614
  return acc;
@@ -2667,8 +2667,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
2667
2667
  }
2668
2668
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2669
2669
  const result = _lodash2.default.cloneDeep(originalRawStructuredText);
2670
- for (const [path14, value] of _lodash2.default.entries(parsedStructuredText)) {
2671
- const realPath = _lodash2.default.chain(path14.split(".")).flatMap((s) => !_lodash2.default.isNaN(_lodash2.default.toNumber(s)) ? ["children", s] : s).value();
2670
+ for (const [path15, value] of _lodash2.default.entries(parsedStructuredText)) {
2671
+ const realPath = _lodash2.default.chain(path15.split(".")).flatMap((s) => !_lodash2.default.isNaN(_lodash2.default.toNumber(s)) ? ["children", s] : s).value();
2672
2672
  const deserializedValue = createRawDatoValue(value, _lodash2.default.get(originalRawStructuredText, realPath), true);
2673
2673
  _lodash2.default.set(result, realPath, deserializedValue);
2674
2674
  }
@@ -3305,7 +3305,16 @@ function _tryParseJSON(line) {
3305
3305
  }
3306
3306
 
3307
3307
  // src/cli/cmd/i18n.ts
3308
- var i18n_default = new (0, _interactivecommander.Command)().command("i18n").description("Run Localization engine").helpOption("-h, --help", "Show help").option("--locale <locale>", "Locale to process", (val, prev) => prev ? [...prev, val] : [val]).option("--bucket <bucket>", "Bucket to process", (val, prev) => prev ? [...prev, val] : [val]).option("--key <key>", "Key to process. Process only a specific translation key, useful for debugging or updating a single entry").option("--frozen", `Run in read-only mode - fails if any translations need updating, useful for CI/CD pipelines to detect missing translations`).option("--force", "Ignore lockfile and process all keys, useful for full re-translation").option("--verbose", "Show detailed output including intermediate processing data and API communication details").option("--interactive", "Enable interactive mode for reviewing and editing translations before they are applied").option("--api-key <api-key>", "Explicitly set the API key to use, override the default API key from settings").option("--debug", "Pause execution at start for debugging purposes, waits for user confirmation before proceeding").option("--strict", "Stop processing on first error instead of continuing with other locales/buckets").action(async function(options) {
3308
+ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").description("Run Localization engine").helpOption("-h, --help", "Show help").option("--locale <locale>", "Locale to process", (val, prev) => prev ? [...prev, val] : [val]).option("--bucket <bucket>", "Bucket to process", (val, prev) => prev ? [...prev, val] : [val]).option(
3309
+ "--key <key>",
3310
+ "Key to process. Process only a specific translation key, useful for debugging or updating a single entry"
3311
+ ).option(
3312
+ "--file [files...]",
3313
+ "File to process. Process only a specific path, may contain asterisk * to match multiple files. Useful if you have a lot of files and want to focus on a specific one. Specify more files separated by commas or spaces."
3314
+ ).option(
3315
+ "--frozen",
3316
+ `Run in read-only mode - fails if any translations need updating, useful for CI/CD pipelines to detect missing translations`
3317
+ ).option("--force", "Ignore lockfile and process all keys, useful for full re-translation").option("--verbose", "Show detailed output including intermediate processing data and API communication details").option("--interactive", "Enable interactive mode for reviewing and editing translations before they are applied").option("--api-key <api-key>", "Explicitly set the API key to use, override the default API key from settings").option("--debug", "Pause execution at start for debugging purposes, waits for user confirmation before proceeding").option("--strict", "Stop processing on first error instead of continuing with other locales/buckets").action(async function(options) {
3309
3318
  updateGitignore();
3310
3319
  const ora = _ora2.default.call(void 0, );
3311
3320
  const flags = parseFlags(options);
@@ -3335,7 +3344,27 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
3335
3344
  buckets = buckets.filter((bucket) => flags.bucket.includes(bucket.type));
3336
3345
  }
3337
3346
  ora.succeed("Buckets retrieved");
3338
- const targetLocales = _optionalChain([flags, 'access', _138 => _138.locale, 'optionalAccess', _139 => _139.length]) ? flags.locale : i18nConfig.locale.targets;
3347
+ if (_optionalChain([flags, 'access', _138 => _138.file, 'optionalAccess', _139 => _139.length])) {
3348
+ buckets = buckets.map((bucket) => {
3349
+ const config = bucket.config.filter(
3350
+ (config2) => flags.file.find((file) => _optionalChain([config2, 'access', _140 => _140.pathPattern, 'optionalAccess', _141 => _141.match, 'call', _142 => _142(file)]))
3351
+ );
3352
+ return { ...bucket, config };
3353
+ }).filter((bucket) => bucket.config.length > 0);
3354
+ if (buckets.length === 0) {
3355
+ ora.fail("No buckets found. All buckets were filtered out by --file option.");
3356
+ process.exit(1);
3357
+ } else {
3358
+ ora.info(`\x1B[36mProcessing only filtered buckets:\x1B[0m`);
3359
+ buckets.map((bucket) => {
3360
+ ora.info(` ${bucket.type}:`);
3361
+ bucket.config.forEach((config) => {
3362
+ ora.info(` - ${config.pathPattern}`);
3363
+ });
3364
+ });
3365
+ }
3366
+ }
3367
+ const targetLocales = _optionalChain([flags, 'access', _143 => _143.locale, 'optionalAccess', _144 => _144.length]) ? flags.locale : i18nConfig.locale.targets;
3339
3368
  const lockfileHelper = createLockfileHelper();
3340
3369
  ora.start("Ensuring i18n.lock exists...");
3341
3370
  if (!lockfileHelper.isLockfileExists()) {
@@ -3630,6 +3659,7 @@ function parseFlags(options) {
3630
3659
  verbose: _zod2.default.boolean().optional(),
3631
3660
  strict: _zod2.default.boolean().optional(),
3632
3661
  key: _zod2.default.string().optional(),
3662
+ file: _zod2.default.array(_zod2.default.string()).optional(),
3633
3663
  interactive: _zod2.default.boolean().default(false),
3634
3664
  debug: _zod2.default.boolean().default(false)
3635
3665
  }).parse(options);
@@ -3665,12 +3695,12 @@ function validateParams(i18nConfig, flags) {
3665
3695
  message: "No buckets found in i18n.json. Please add at least one bucket containing i18n content.",
3666
3696
  docUrl: "bucketNotFound"
3667
3697
  });
3668
- } else if (_optionalChain([flags, 'access', _140 => _140.locale, 'optionalAccess', _141 => _141.some, 'call', _142 => _142((locale) => !i18nConfig.locale.targets.includes(locale))])) {
3698
+ } else if (_optionalChain([flags, 'access', _145 => _145.locale, 'optionalAccess', _146 => _146.some, 'call', _147 => _147((locale) => !i18nConfig.locale.targets.includes(locale))])) {
3669
3699
  throw new CLIError({
3670
3700
  message: `One or more specified locales do not exist in i18n.json locale.targets. Please add them to the list and try again.`,
3671
3701
  docUrl: "localeTargetNotFound"
3672
3702
  });
3673
- } else if (_optionalChain([flags, 'access', _143 => _143.bucket, 'optionalAccess', _144 => _144.some, 'call', _145 => _145((bucket) => !i18nConfig.buckets[bucket])])) {
3703
+ } else if (_optionalChain([flags, 'access', _148 => _148.bucket, 'optionalAccess', _149 => _149.some, 'call', _150 => _150((bucket) => !i18nConfig.buckets[bucket])])) {
3674
3704
  throw new CLIError({
3675
3705
  message: `One or more specified buckets do not exist in i18n.json. Please add them to the list and try again.`,
3676
3706
  docUrl: "bucketNotFound"
@@ -3953,10 +3983,637 @@ var mcp_default = new (0, _interactivecommander.Command)().command("mcp").descri
3953
3983
  console.log("Lingo.dev MCP Server running on stdio");
3954
3984
  });
3955
3985
 
3986
+ // src/cli/cmd/ci.ts
3987
+
3988
+
3989
+ // ../../action/src/main.ts
3990
+
3991
+
3992
+ // ../../action/src/flows/pull-request.ts
3993
+
3994
+
3995
+ // ../../action/src/flows/in-branch.ts
3996
+
3997
+
3998
+
3999
+ // ../../action/src/flows/_base.ts
4000
+ var IntegrationFlow = class {
4001
+ constructor(ora, platformKit) {
4002
+ this.ora = ora;
4003
+ this.platformKit = platformKit;
4004
+ }
4005
+
4006
+ };
4007
+ var gitConfig = {
4008
+ userName: "Lingo.dev",
4009
+ userEmail: "support@lingo.dev"
4010
+ };
4011
+
4012
+ // ../../action/src/flows/in-branch.ts
4013
+ var InBranchFlow = class extends IntegrationFlow {
4014
+ async preRun() {
4015
+ this.ora.start("Configuring git");
4016
+ const canContinue = this.configureGit();
4017
+ this.ora.succeed("Git configured");
4018
+ return canContinue;
4019
+ }
4020
+ async run(forcePush = false) {
4021
+ this.ora.start("Running Lingo.dev");
4022
+ await this.runLingoDotDev();
4023
+ this.ora.succeed("Done running Lingo.dev");
4024
+ _child_process.execSync.call(void 0, `rm -f i18n.cache`, { stdio: "inherit" });
4025
+ this.ora.start("Checking for changes");
4026
+ const hasChanges = this.checkCommitableChanges();
4027
+ this.ora.succeed(hasChanges ? "Changes detected" : "No changes detected");
4028
+ if (hasChanges) {
4029
+ this.ora.start("Committing changes");
4030
+ _child_process.execSync.call(void 0, `git add .`, { stdio: "inherit" });
4031
+ _child_process.execSync.call(void 0, `git status --porcelain`, { stdio: "inherit" });
4032
+ _child_process.execSync.call(void 0, `git commit -m "${this.platformKit.config.commitMessage}"`, {
4033
+ stdio: "inherit"
4034
+ });
4035
+ this.ora.succeed("Changes committed");
4036
+ this.ora.start("Pushing changes to remote");
4037
+ const currentBranch = _nullishCoalesce(this.i18nBranchName, () => ( this.platformKit.platformConfig.baseBranchName));
4038
+ _child_process.execSync.call(void 0, `git push origin ${currentBranch} ${forcePush ? "--force" : ""}`, {
4039
+ stdio: "inherit"
4040
+ });
4041
+ this.ora.succeed("Changes pushed to remote");
4042
+ }
4043
+ return hasChanges;
4044
+ }
4045
+ checkCommitableChanges() {
4046
+ return _child_process.execSync.call(void 0, 'git status --porcelain || echo "has_changes"', {
4047
+ encoding: "utf8"
4048
+ }).length > 0;
4049
+ }
4050
+ async runLingoDotDev() {
4051
+ _child_process.execSync.call(void 0, `npx lingo.dev@latest i18n --api-key ${this.platformKit.config.replexicaApiKey}`, { stdio: "inherit" });
4052
+ }
4053
+ configureGit() {
4054
+ const { processOwnCommits } = this.platformKit.config;
4055
+ const { baseBranchName } = this.platformKit.platformConfig;
4056
+ this.ora.info(`Current working directory:`);
4057
+ _child_process.execSync.call(void 0, `pwd`, { stdio: "inherit" });
4058
+ _child_process.execSync.call(void 0, `ls -la`, { stdio: "inherit" });
4059
+ _child_process.execSync.call(void 0, `git config --global safe.directory ${process.cwd()}`);
4060
+ _child_process.execSync.call(void 0, `git config user.name "${gitConfig.userName}"`);
4061
+ _child_process.execSync.call(void 0, `git config user.email "${gitConfig.userEmail}"`);
4062
+ _optionalChain([this, 'access', _151 => _151.platformKit, 'optionalAccess', _152 => _152.gitConfig, 'call', _153 => _153()]);
4063
+ _child_process.execSync.call(void 0, `git fetch origin ${baseBranchName}`, { stdio: "inherit" });
4064
+ _child_process.execSync.call(void 0, `git checkout ${baseBranchName} --`, { stdio: "inherit" });
4065
+ if (!processOwnCommits) {
4066
+ const currentAuthor = `${gitConfig.userName} <${gitConfig.userEmail}>`;
4067
+ const authorOfLastCommit = _child_process.execSync.call(void 0, `git log -1 --pretty=format:'%an <%ae>'`).toString();
4068
+ if (authorOfLastCommit === currentAuthor) {
4069
+ this.ora.warn(
4070
+ `The last commit was already made by ${currentAuthor}, so this run will be skipped, as running again would have no effect. See docs: https://docs.lingo.dev/ci-action/overview`
4071
+ );
4072
+ return false;
4073
+ }
4074
+ }
4075
+ const workingDir = _path2.default.resolve(process.cwd(), this.platformKit.config.workingDir);
4076
+ if (workingDir !== process.cwd()) {
4077
+ this.ora.info(`Changing to working directory: ${this.platformKit.config.workingDir}`);
4078
+ process.chdir(workingDir);
4079
+ }
4080
+ return true;
4081
+ }
4082
+ };
4083
+
4084
+ // ../../action/src/flows/pull-request.ts
4085
+ var PullRequestFlow = class extends InBranchFlow {
4086
+ async preRun() {
4087
+ const canContinue = await _optionalChain([super.preRun.bind(this), 'optionalCall', _154 => _154()]);
4088
+ if (!canContinue) {
4089
+ return false;
4090
+ }
4091
+ this.ora.start("Calculating automated branch name");
4092
+ this.i18nBranchName = this.calculatePrBranchName();
4093
+ this.ora.succeed(`Automated branch name calculated: ${this.i18nBranchName}`);
4094
+ this.ora.start("Checking if branch exists");
4095
+ const branchExists = await this.checkBranchExistance(this.i18nBranchName);
4096
+ this.ora.succeed(branchExists ? "Branch exists" : "Branch does not exist");
4097
+ if (branchExists) {
4098
+ this.ora.start(`Checking out branch ${this.i18nBranchName}`);
4099
+ this.checkoutI18nBranch(this.i18nBranchName);
4100
+ this.ora.succeed(`Checked out branch ${this.i18nBranchName}`);
4101
+ this.ora.start(`Syncing with ${this.platformKit.platformConfig.baseBranchName}`);
4102
+ this.syncI18nBranch();
4103
+ this.ora.succeed(`Checked out and synced branch ${this.i18nBranchName}`);
4104
+ } else {
4105
+ this.ora.start(`Creating branch ${this.i18nBranchName}`);
4106
+ this.createI18nBranch(this.i18nBranchName);
4107
+ this.ora.succeed(`Created branch ${this.i18nBranchName}`);
4108
+ }
4109
+ return true;
4110
+ }
4111
+ async run() {
4112
+ return super.run(true);
4113
+ }
4114
+ async postRun() {
4115
+ if (!this.i18nBranchName) {
4116
+ throw new Error("i18nBranchName is not set. Did you forget to call preRun?");
4117
+ }
4118
+ this.ora.start("Checking if PR already exists");
4119
+ const pullRequestNumber = await this.ensureFreshPr(this.i18nBranchName);
4120
+ this.ora.succeed(`Pull request ready: ${this.platformKit.buildPullRequestUrl(pullRequestNumber)}`);
4121
+ }
4122
+ calculatePrBranchName() {
4123
+ return `lingo.dev/${this.platformKit.platformConfig.baseBranchName}`;
4124
+ }
4125
+ async checkBranchExistance(prBranchName) {
4126
+ return this.platformKit.branchExists({
4127
+ branch: prBranchName
4128
+ });
4129
+ }
4130
+ async ensureFreshPr(i18nBranchName) {
4131
+ this.ora.start(
4132
+ `Checking for existing PR with head ${i18nBranchName} and base ${this.platformKit.platformConfig.baseBranchName}`
4133
+ );
4134
+ const existingPrNumber = await this.platformKit.getOpenPullRequestNumber({
4135
+ branch: i18nBranchName
4136
+ });
4137
+ this.ora.succeed(existingPrNumber ? "PR found" : "No PR found");
4138
+ if (existingPrNumber) {
4139
+ this.ora.start(`Closing existing PR ${existingPrNumber}`);
4140
+ await this.platformKit.closePullRequest({
4141
+ pullRequestNumber: existingPrNumber
4142
+ });
4143
+ this.ora.succeed(`Closed existing PR ${existingPrNumber}`);
4144
+ }
4145
+ this.ora.start(`Creating new PR`);
4146
+ const newPrNumber = await this.platformKit.createPullRequest({
4147
+ head: i18nBranchName,
4148
+ title: this.platformKit.config.pullRequestTitle,
4149
+ body: this.getPrBodyContent()
4150
+ });
4151
+ this.ora.succeed(`Created new PR ${newPrNumber}`);
4152
+ if (existingPrNumber) {
4153
+ this.ora.start(`Posting comment about outdated PR ${existingPrNumber}`);
4154
+ await this.platformKit.commentOnPullRequest({
4155
+ pullRequestNumber: existingPrNumber,
4156
+ body: `This PR is now outdated. A new version has been created at ${this.platformKit.buildPullRequestUrl(
4157
+ newPrNumber
4158
+ )}`
4159
+ });
4160
+ this.ora.succeed(`Posted comment about outdated PR ${existingPrNumber}`);
4161
+ }
4162
+ return newPrNumber;
4163
+ }
4164
+ checkoutI18nBranch(i18nBranchName) {
4165
+ _child_process.execSync.call(void 0, `git fetch origin ${i18nBranchName}`, { stdio: "inherit" });
4166
+ _child_process.execSync.call(void 0, `git checkout -b ${i18nBranchName}`, {
4167
+ stdio: "inherit"
4168
+ });
4169
+ }
4170
+ createI18nBranch(i18nBranchName) {
4171
+ try {
4172
+ _child_process.execSync.call(void 0, `git fetch origin ${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
4173
+ _child_process.execSync.call(void 0, `git checkout -b ${i18nBranchName} origin/${this.platformKit.platformConfig.baseBranchName}`, {
4174
+ stdio: "inherit"
4175
+ });
4176
+ } catch (error) {
4177
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
4178
+ this.ora.fail(`Failed to create branch: ${errorMessage}`);
4179
+ this.ora.info(`
4180
+ Troubleshooting tips:
4181
+ 1. Make sure you have permission to create branches
4182
+ 2. Check if the branch already exists locally (try 'git branch -a')
4183
+ 3. Verify connectivity to remote repository
4184
+ `);
4185
+ throw new Error(`Branch creation failed: ${errorMessage}`);
4186
+ }
4187
+ }
4188
+ syncI18nBranch() {
4189
+ if (!this.i18nBranchName) {
4190
+ throw new Error("i18nBranchName is not set");
4191
+ }
4192
+ this.ora.start(`Fetching latest changes from ${this.platformKit.platformConfig.baseBranchName}`);
4193
+ _child_process.execSync.call(void 0, `git fetch origin ${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
4194
+ this.ora.succeed(`Fetched latest changes from ${this.platformKit.platformConfig.baseBranchName}`);
4195
+ try {
4196
+ this.ora.start("Attempting to rebase branch");
4197
+ _child_process.execSync.call(void 0, `git rebase origin/${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
4198
+ this.ora.succeed("Successfully rebased branch");
4199
+ } catch (error) {
4200
+ this.ora.warn("Rebase failed, falling back to alternative sync method");
4201
+ this.ora.start("Aborting failed rebase");
4202
+ _child_process.execSync.call(void 0, "git rebase --abort", { stdio: "inherit" });
4203
+ this.ora.succeed("Aborted failed rebase");
4204
+ this.ora.start(`Resetting to ${this.platformKit.platformConfig.baseBranchName}`);
4205
+ _child_process.execSync.call(void 0, `git reset --hard origin/${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
4206
+ this.ora.succeed(`Reset to ${this.platformKit.platformConfig.baseBranchName}`);
4207
+ this.ora.start("Restoring target files");
4208
+ const targetFiles = ["i18n.lock"];
4209
+ const targetFileNames = _child_process.execSync.call(void 0,
4210
+ `npx lingo.dev@latest show files --target ${this.platformKit.platformConfig.baseBranchName}`,
4211
+ { encoding: "utf8" }
4212
+ ).split("\n").filter(Boolean);
4213
+ targetFiles.push(...targetFileNames);
4214
+ _child_process.execSync.call(void 0, `git fetch origin ${this.i18nBranchName}`, { stdio: "inherit" });
4215
+ for (const file of targetFiles) {
4216
+ try {
4217
+ _child_process.execSync.call(void 0, `git checkout FETCH_HEAD -- ${file}`, { stdio: "inherit" });
4218
+ } catch (error2) {
4219
+ this.ora.warn(`Skipping non-existent file: ${file}`);
4220
+ continue;
4221
+ }
4222
+ }
4223
+ this.ora.succeed("Restored target files");
4224
+ }
4225
+ this.ora.start("Checking for changes to commit");
4226
+ const hasChanges = this.checkCommitableChanges();
4227
+ if (hasChanges) {
4228
+ _child_process.execSync.call(void 0, "git add .", { stdio: "inherit" });
4229
+ _child_process.execSync.call(void 0, `git commit -m "chore: sync with ${this.platformKit.platformConfig.baseBranchName}"`, {
4230
+ stdio: "inherit"
4231
+ });
4232
+ this.ora.succeed("Committed additional changes");
4233
+ } else {
4234
+ this.ora.succeed("No changes to commit");
4235
+ }
4236
+ }
4237
+ getPrBodyContent() {
4238
+ return `
4239
+ Hey team,
4240
+
4241
+ [**Lingo.dev**](https://lingo.dev) here with fresh translations!
4242
+
4243
+ ### In this update
4244
+
4245
+ - Added missing translations
4246
+ - Performed brand voice, context and glossary checks
4247
+ - Enhanced translations using Lingo.dev Localization Engine
4248
+
4249
+ ### Next Steps
4250
+
4251
+ - [ ] Review the changes
4252
+ - [ ] Merge when ready
4253
+ `.trim();
4254
+ }
4255
+ };
4256
+
4257
+ // ../../action/src/platforms/bitbucket.ts
4258
+
4259
+ var _bitbucket = require('bitbucket'); var _bitbucket2 = _interopRequireDefault(_bitbucket);
4260
+
4261
+
4262
+ // ../../action/src/platforms/_base.ts
4263
+
4264
+ var defaultMessage = "feat: update translations via @lingodotdev";
4265
+ var PlatformKit = class {
4266
+ gitConfig() {
4267
+ }
4268
+ get config() {
4269
+ const env = _zod2.default.object({
4270
+ LINGODOTDEV_API_KEY: _zod2.default.string(),
4271
+ LINGODOTDEV_PULL_REQUEST: _zod2.default.preprocess((val) => val === "true" || val === true, _zod2.default.boolean()),
4272
+ LINGODOTDEV_COMMIT_MESSAGE: _zod2.default.string().optional(),
4273
+ LINGODOTDEV_PULL_REQUEST_TITLE: _zod2.default.string().optional(),
4274
+ LINGODOTDEV_WORKING_DIRECTORY: _zod2.default.string().optional(),
4275
+ LINGODOTDEV_PROCESS_OWN_COMMITS: _zod2.default.preprocess((val) => val === "true" || val === true, _zod2.default.boolean()).optional()
4276
+ }).parse(process.env);
4277
+ return {
4278
+ replexicaApiKey: env.LINGODOTDEV_API_KEY,
4279
+ isPullRequestMode: env.LINGODOTDEV_PULL_REQUEST,
4280
+ commitMessage: env.LINGODOTDEV_COMMIT_MESSAGE || defaultMessage,
4281
+ pullRequestTitle: env.LINGODOTDEV_PULL_REQUEST_TITLE || defaultMessage,
4282
+ workingDir: env.LINGODOTDEV_WORKING_DIRECTORY || ".",
4283
+ processOwnCommits: env.LINGODOTDEV_PROCESS_OWN_COMMITS || false
4284
+ };
4285
+ }
4286
+ };
4287
+
4288
+ // ../../action/src/platforms/bitbucket.ts
4289
+ var { Bitbucket } = _bitbucket2.default;
4290
+ var BitbucketPlatformKit = class extends PlatformKit {
4291
+
4292
+ get bb() {
4293
+ if (!this._bb) {
4294
+ this._bb = new Bitbucket({
4295
+ auth: { token: this.platformConfig.bbToken || "" }
4296
+ });
4297
+ }
4298
+ return this._bb;
4299
+ }
4300
+ async branchExists({ branch }) {
4301
+ return await this.bb.repositories.getBranch({
4302
+ workspace: this.platformConfig.repositoryOwner,
4303
+ repo_slug: this.platformConfig.repositoryName,
4304
+ name: branch
4305
+ }).then((r) => r.data).then((v) => !!v).catch((r) => r.status === 404 ? false : Promise.reject(r));
4306
+ }
4307
+ async getOpenPullRequestNumber({ branch }) {
4308
+ return await this.bb.repositories.listPullRequests({
4309
+ workspace: this.platformConfig.repositoryOwner,
4310
+ repo_slug: this.platformConfig.repositoryName,
4311
+ state: "OPEN"
4312
+ }).then(({ data: { values } }) => {
4313
+ return _optionalChain([values, 'optionalAccess', _155 => _155.find, 'call', _156 => _156(
4314
+ ({ source, destination }) => _optionalChain([source, 'optionalAccess', _157 => _157.branch, 'optionalAccess', _158 => _158.name]) === branch && _optionalChain([destination, 'optionalAccess', _159 => _159.branch, 'optionalAccess', _160 => _160.name]) === this.platformConfig.baseBranchName
4315
+ )]);
4316
+ }).then((pr) => _optionalChain([pr, 'optionalAccess', _161 => _161.id]));
4317
+ }
4318
+ async closePullRequest({ pullRequestNumber }) {
4319
+ await this.bb.repositories.declinePullRequest({
4320
+ workspace: this.platformConfig.repositoryOwner,
4321
+ repo_slug: this.platformConfig.repositoryName,
4322
+ pull_request_id: pullRequestNumber
4323
+ });
4324
+ }
4325
+ async createPullRequest({ title, body, head }) {
4326
+ return await this.bb.repositories.createPullRequest({
4327
+ workspace: this.platformConfig.repositoryOwner,
4328
+ repo_slug: this.platformConfig.repositoryName,
4329
+ _body: {
4330
+ title,
4331
+ description: body,
4332
+ source: { branch: { name: head } },
4333
+ destination: { branch: { name: this.platformConfig.baseBranchName } }
4334
+ }
4335
+ }).then(({ data }) => _nullishCoalesce(data.id, () => ( 0)));
4336
+ }
4337
+ async commentOnPullRequest({ pullRequestNumber, body }) {
4338
+ await this.bb.repositories.createPullRequestComment({
4339
+ workspace: this.platformConfig.repositoryOwner,
4340
+ repo_slug: this.platformConfig.repositoryName,
4341
+ pull_request_id: pullRequestNumber,
4342
+ _body: {
4343
+ content: {
4344
+ raw: body
4345
+ }
4346
+ }
4347
+ });
4348
+ }
4349
+ async gitConfig() {
4350
+ _child_process.execSync.call(void 0, "git config --unset http.${BITBUCKET_GIT_HTTP_ORIGIN}.proxy", {
4351
+ stdio: "inherit"
4352
+ });
4353
+ _child_process.execSync.call(void 0, "git config http.${BITBUCKET_GIT_HTTP_ORIGIN}.proxy http://host.docker.internal:29418/", {
4354
+ stdio: "inherit"
4355
+ });
4356
+ }
4357
+ get platformConfig() {
4358
+ const env = _zod2.default.object({
4359
+ BITBUCKET_BRANCH: _zod2.default.string(),
4360
+ BITBUCKET_REPO_FULL_NAME: _zod2.default.string(),
4361
+ BB_TOKEN: _zod2.default.string().optional()
4362
+ }).parse(process.env);
4363
+ const [repositoryOwner, repositoryName] = env.BITBUCKET_REPO_FULL_NAME.split("/");
4364
+ return {
4365
+ baseBranchName: env.BITBUCKET_BRANCH,
4366
+ repositoryOwner,
4367
+ repositoryName,
4368
+ bbToken: env.BB_TOKEN
4369
+ };
4370
+ }
4371
+ buildPullRequestUrl(pullRequestNumber) {
4372
+ const { repositoryOwner, repositoryName } = this.platformConfig;
4373
+ return `https://bitbucket.org/${repositoryOwner}/${repositoryName}/pull-requests/${pullRequestNumber}`;
4374
+ }
4375
+ };
4376
+
4377
+ // ../../action/src/platforms/github.ts
4378
+ var _octokit2 = require('octokit');
4379
+
4380
+
4381
+ var GitHubPlatformKit = class extends PlatformKit {
4382
+
4383
+ get octokit() {
4384
+ if (!this._octokit) {
4385
+ this._octokit = new (0, _octokit2.Octokit)({ auth: this.platformConfig.ghToken });
4386
+ }
4387
+ return this._octokit;
4388
+ }
4389
+ async branchExists({ branch }) {
4390
+ return await this.octokit.rest.repos.getBranch({
4391
+ branch,
4392
+ owner: this.platformConfig.repositoryOwner,
4393
+ repo: this.platformConfig.repositoryName
4394
+ }).then((r) => r.data).then((v) => !!v).catch((r) => r.status === 404 ? false : Promise.reject(r));
4395
+ }
4396
+ async getOpenPullRequestNumber({ branch }) {
4397
+ return await this.octokit.rest.pulls.list({
4398
+ head: `${this.platformConfig.repositoryOwner}:${branch}`,
4399
+ owner: this.platformConfig.repositoryOwner,
4400
+ repo: this.platformConfig.repositoryName,
4401
+ base: this.platformConfig.baseBranchName,
4402
+ state: "open"
4403
+ }).then(({ data }) => data[0]).then((pr) => _optionalChain([pr, 'optionalAccess', _162 => _162.number]));
4404
+ }
4405
+ async closePullRequest({ pullRequestNumber }) {
4406
+ await this.octokit.rest.pulls.update({
4407
+ pull_number: pullRequestNumber,
4408
+ owner: this.platformConfig.repositoryOwner,
4409
+ repo: this.platformConfig.repositoryName,
4410
+ state: "closed"
4411
+ });
4412
+ }
4413
+ async createPullRequest({ head, title, body }) {
4414
+ return await this.octokit.rest.pulls.create({
4415
+ head,
4416
+ title,
4417
+ body,
4418
+ owner: this.platformConfig.repositoryOwner,
4419
+ repo: this.platformConfig.repositoryName,
4420
+ base: this.platformConfig.baseBranchName
4421
+ }).then(({ data }) => data.number);
4422
+ }
4423
+ async commentOnPullRequest({ pullRequestNumber, body }) {
4424
+ await this.octokit.rest.issues.createComment({
4425
+ issue_number: pullRequestNumber,
4426
+ body,
4427
+ owner: this.platformConfig.repositoryOwner,
4428
+ repo: this.platformConfig.repositoryName
4429
+ });
4430
+ }
4431
+ async gitConfig() {
4432
+ const { ghToken, repositoryOwner, repositoryName } = this.platformConfig;
4433
+ const { processOwnCommits } = this.config;
4434
+ if (ghToken && processOwnCommits) {
4435
+ console.log("Using provided GH_TOKEN. This will trigger your CI/CD pipeline to run again.");
4436
+ const url = `https://${ghToken}@github.com/${repositoryOwner}/${repositoryName}.git`;
4437
+ _child_process.execSync.call(void 0, `git remote set-url origin ${url}`, {
4438
+ stdio: "inherit"
4439
+ });
4440
+ }
4441
+ }
4442
+ get platformConfig() {
4443
+ const env = _zod2.default.object({
4444
+ GITHUB_REPOSITORY: _zod2.default.string(),
4445
+ GITHUB_REPOSITORY_OWNER: _zod2.default.string(),
4446
+ GITHUB_REF_NAME: _zod2.default.string(),
4447
+ GITHUB_HEAD_REF: _zod2.default.string(),
4448
+ GH_TOKEN: _zod2.default.string().optional()
4449
+ }).parse(process.env);
4450
+ const baseBranchName = !env.GITHUB_REF_NAME.endsWith("/merge") ? env.GITHUB_REF_NAME : env.GITHUB_HEAD_REF;
4451
+ return {
4452
+ ghToken: env.GH_TOKEN,
4453
+ baseBranchName,
4454
+ repositoryOwner: env.GITHUB_REPOSITORY_OWNER,
4455
+ repositoryName: env.GITHUB_REPOSITORY.split("/")[1]
4456
+ };
4457
+ }
4458
+ buildPullRequestUrl(pullRequestNumber) {
4459
+ const { repositoryOwner, repositoryName } = this.platformConfig;
4460
+ return `https://github.com/${repositoryOwner}/${repositoryName}/pull/${pullRequestNumber}`;
4461
+ }
4462
+ };
4463
+
4464
+ // ../../action/src/platforms/gitlab.ts
4465
+ var _rest = require('@gitbeaker/rest');
4466
+
4467
+
4468
+ var gl = new (0, _rest.Gitlab)({ token: "" });
4469
+ var GitlabPlatformKit = class extends PlatformKit {
4470
+
4471
+ constructor() {
4472
+ super();
4473
+ process.chdir(this.platformConfig.projectDir);
4474
+ }
4475
+ get gitlab() {
4476
+ if (!this._gitlab) {
4477
+ this._gitlab = new (0, _rest.Gitlab)({
4478
+ token: this.platformConfig.glToken || ""
4479
+ });
4480
+ }
4481
+ return this._gitlab;
4482
+ }
4483
+ get platformConfig() {
4484
+ const env = _zod2.default.object({
4485
+ GL_TOKEN: _zod2.default.string().optional(),
4486
+ CI_COMMIT_BRANCH: _zod2.default.string(),
4487
+ CI_MERGE_REQUEST_SOURCE_BRANCH_NAME: _zod2.default.string().optional(),
4488
+ CI_PROJECT_NAMESPACE: _zod2.default.string(),
4489
+ CI_PROJECT_NAME: _zod2.default.string(),
4490
+ CI_PROJECT_ID: _zod2.default.string(),
4491
+ CI_PROJECT_DIR: _zod2.default.string(),
4492
+ CI_REPOSITORY_URL: _zod2.default.string()
4493
+ }).parse(process.env);
4494
+ const config = {
4495
+ glToken: env.GL_TOKEN,
4496
+ baseBranchName: _nullishCoalesce(env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME, () => ( env.CI_COMMIT_BRANCH)),
4497
+ repositoryOwner: env.CI_PROJECT_NAMESPACE,
4498
+ repositoryName: env.CI_PROJECT_NAME,
4499
+ gitlabProjectId: env.CI_PROJECT_ID,
4500
+ projectDir: env.CI_PROJECT_DIR,
4501
+ reporitoryUrl: env.CI_REPOSITORY_URL
4502
+ };
4503
+ return config;
4504
+ }
4505
+ async branchExists({ branch }) {
4506
+ try {
4507
+ await this.gitlab.Branches.show(this.platformConfig.gitlabProjectId, branch);
4508
+ return true;
4509
+ } catch (e2) {
4510
+ return false;
4511
+ }
4512
+ }
4513
+ async getOpenPullRequestNumber({ branch }) {
4514
+ const mergeRequests = await this.gitlab.MergeRequests.all({
4515
+ projectId: this.platformConfig.gitlabProjectId,
4516
+ sourceBranch: branch,
4517
+ state: "opened"
4518
+ });
4519
+ return _optionalChain([mergeRequests, 'access', _163 => _163[0], 'optionalAccess', _164 => _164.iid]);
4520
+ }
4521
+ async closePullRequest({ pullRequestNumber }) {
4522
+ await this.gitlab.MergeRequests.edit(this.platformConfig.gitlabProjectId, pullRequestNumber, {
4523
+ stateEvent: "close"
4524
+ });
4525
+ }
4526
+ async createPullRequest({ head, title, body }) {
4527
+ const mr = await this.gitlab.MergeRequests.create(
4528
+ this.platformConfig.gitlabProjectId,
4529
+ head,
4530
+ this.platformConfig.baseBranchName,
4531
+ title,
4532
+ {
4533
+ description: body
4534
+ }
4535
+ );
4536
+ return mr.iid;
4537
+ }
4538
+ async commentOnPullRequest({ pullRequestNumber, body }) {
4539
+ await this.gitlab.MergeRequestNotes.create(this.platformConfig.gitlabProjectId, pullRequestNumber, body);
4540
+ }
4541
+ gitConfig() {
4542
+ const url = `https://oauth2:${this.platformConfig.glToken}@gitlab.com/${this.platformConfig.repositoryOwner}/${this.platformConfig.repositoryName}.git`;
4543
+ _child_process.execSync.call(void 0, `git remote set-url origin ${url}`, {
4544
+ stdio: "inherit"
4545
+ });
4546
+ }
4547
+ buildPullRequestUrl(pullRequestNumber) {
4548
+ return `https://gitlab.com/${this.platformConfig.repositoryOwner}/${this.platformConfig.repositoryName}/-/merge_requests/${pullRequestNumber}`;
4549
+ }
4550
+ };
4551
+
4552
+ // ../../action/src/platforms/index.ts
4553
+ var getPlatformKit = () => {
4554
+ if (process.env.BITBUCKET_PIPELINE_UUID) {
4555
+ return new BitbucketPlatformKit();
4556
+ }
4557
+ if (process.env.GITHUB_ACTION) {
4558
+ return new GitHubPlatformKit();
4559
+ }
4560
+ if (process.env.GITLAB_CI) {
4561
+ return new GitlabPlatformKit();
4562
+ }
4563
+ throw new Error("This platform is not supported");
4564
+ };
4565
+
4566
+ // ../../action/src/main.ts
4567
+ async function main() {
4568
+ const ora = _ora2.default.call(void 0, );
4569
+ const platformKit = getPlatformKit();
4570
+ const { isPullRequestMode } = platformKit.config;
4571
+ ora.info(`Pull request mode: ${isPullRequestMode ? "on" : "off"}`);
4572
+ const flow = isPullRequestMode ? new PullRequestFlow(ora, platformKit) : new InBranchFlow(ora, platformKit);
4573
+ const canRun = await _optionalChain([flow, 'access', _165 => _165.preRun, 'optionalCall', _166 => _166()]);
4574
+ if (canRun === false) {
4575
+ return;
4576
+ }
4577
+ const hasChanges = await flow.run();
4578
+ if (!hasChanges) {
4579
+ return;
4580
+ }
4581
+ await _optionalChain([flow, 'access', _167 => _167.postRun, 'optionalCall', _168 => _168()]);
4582
+ }
4583
+
4584
+ // src/cli/cmd/ci.ts
4585
+ var ci_default = new (0, _interactivecommander.Command)().command("ci").description("Run Lingo.dev CI/CD action").helpOption("-h, --help", "Show help").option("--pull-request", "Create a pull request with the changes", false).option("--commit-message <message>", "Commit message").option("--pull-request-title <title>", "Pull request title").option("--working-directory <dir>", "Working directory").option("--process-own-commits", "Process commits made by this action", false).action(async (options, program) => {
4586
+ const apiKey = program.args[0];
4587
+ const settings = getSettings(apiKey);
4588
+ if (!settings.auth.apiKey) {
4589
+ console.error("No API key provided");
4590
+ return;
4591
+ }
4592
+ const authenticator = createAuthenticator({
4593
+ apiUrl: settings.auth.apiUrl,
4594
+ apiKey: settings.auth.apiKey
4595
+ });
4596
+ const auth = await authenticator.whoami();
4597
+ if (!auth) {
4598
+ console.error("Not authenticated");
4599
+ return;
4600
+ }
4601
+ const env = {
4602
+ LINGODOTDEV_API_KEY: settings.auth.apiKey,
4603
+ LINGODOTDEV_PULL_REQUEST: _optionalChain([options, 'access', _169 => _169.pullRequest, 'optionalAccess', _170 => _170.toString, 'call', _171 => _171()]) || "false",
4604
+ ...options.commitMessage && { LINGODOTDEV_COMMIT_MESSAGE: options.commitMessage },
4605
+ ...options.pullRequestTitle && { LINGODOTDEV_PULL_REQUEST_TITLE: options.pullRequestTitle },
4606
+ ...options.workingDirectory && { LINGODOTDEV_WORKING_DIRECTORY: options.workingDirectory },
4607
+ ...options.processOwnCommits && { LINGODOTDEV_PROCESS_OWN_COMMITS: options.processOwnCommits.toString() }
4608
+ };
4609
+ process.env = { ...process.env, ...env };
4610
+ main();
4611
+ });
4612
+
3956
4613
  // package.json
3957
4614
  var package_default = {
3958
4615
  name: "lingo.dev",
3959
- version: "0.78.17",
4616
+ version: "0.79.1",
3960
4617
  description: "Lingo.dev CLI",
3961
4618
  private: false,
3962
4619
  publishConfig: {
@@ -4014,11 +4671,13 @@ var package_default = {
4014
4671
  license: "Apache-2.0",
4015
4672
  dependencies: {
4016
4673
  "@datocms/cma-client-node": "^3.4.0",
4674
+ "@gitbeaker/rest": "^39.34.3",
4017
4675
  "@inquirer/prompts": "^7.2.3",
4018
4676
  "@lingo.dev/_sdk": "workspace:*",
4019
4677
  "@lingo.dev/_spec": "workspace:*",
4020
4678
  "@modelcontextprotocol/sdk": "^1.5.0",
4021
4679
  "@paralleldrive/cuid2": "^2.2.2",
4680
+ bitbucket: "^2.12.0",
4022
4681
  chalk: "^5.4.1",
4023
4682
  cors: "^2.8.5",
4024
4683
  "csv-parse": "^5.6.0",
@@ -4048,6 +4707,7 @@ var package_default = {
4048
4707
  marked: "^15.0.6",
4049
4708
  "node-webvtt": "^1.9.4",
4050
4709
  "object-hash": "^3.0.0",
4710
+ octokit: "^4.0.2",
4051
4711
  open: "^10.1.0",
4052
4712
  ora: "^8.1.1",
4053
4713
  "p-limit": "^6.2.0",
@@ -4107,7 +4767,7 @@ ${_gradientstring.vice.call(void 0,
4107
4767
 
4108
4768
  Website: https://lingo.dev
4109
4769
  `
4110
- ).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(show_default).addCommand(lockfile_default).addCommand(cleanup_default).addCommand(mcp_default).exitOverride((err) => {
4770
+ ).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(show_default).addCommand(lockfile_default).addCommand(cleanup_default).addCommand(mcp_default).addCommand(ci_default).exitOverride((err) => {
4111
4771
  if (err.code === "commander.helpDisplayed" || err.code === "commander.version" || err.code === "commander.help") {
4112
4772
  process.exit(0);
4113
4773
  }