@fern-api/generator-cli 0.6.11 → 0.6.14

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/dist/api.d.ts CHANGED
@@ -532,6 +532,12 @@ interface GithubStepConfig {
532
532
  branch?: string;
533
533
  /** Commit message for the generation */
534
534
  commitMessage?: string;
535
+ /** User-facing changelog entry for PR body. When present, used instead of commit message body. */
536
+ changelogEntry?: string;
537
+ /** Structured PR description with Before/After code fences for breaking changes. Takes priority over changelogEntry for PR body. */
538
+ prDescription?: string;
539
+ /** One-sentence justification for WHY the version bump was chosen. Prepended to PR body when present. */
540
+ versionBumpReason?: string;
535
541
  /** Skip push/PR creation, just prepare branches locally */
536
542
  previewMode?: boolean;
537
543
  /** Generator name for namespaced fern-generation-base tag */
package/dist/api.js CHANGED
@@ -902,7 +902,7 @@ module.exports = __toCommonJS(api_exports2);
902
902
  var import_promises = require("fs/promises");
903
903
  var import_path = __toESM(require("path"), 1);
904
904
 
905
- // ../../node_modules/.pnpm/simple-git@3.30.0/node_modules/simple-git/dist/esm/index.js
905
+ // ../../node_modules/.pnpm/simple-git@3.33.0/node_modules/simple-git/dist/esm/index.js
906
906
  var import_node_buffer = require("buffer");
907
907
  var import_file_exists = __toESM(require_dist(), 1);
908
908
  var import_debug = __toESM(require_src(), 1);
@@ -1153,7 +1153,7 @@ var init_argument_filters = __esm({
1153
1153
  return typeof input === "number";
1154
1154
  };
1155
1155
  filterString = (input) => {
1156
- return typeof input === "string";
1156
+ return typeof input === "string" || isPathSpec(input);
1157
1157
  };
1158
1158
  filterStringOrStringArray = (input) => {
1159
1159
  return filterString(input) || Array.isArray(input) && input.every(filterString);
@@ -3528,15 +3528,15 @@ function parser3(indexX, indexY, handler) {
3528
3528
  return [`${indexX}${indexY}`, handler];
3529
3529
  }
3530
3530
  function conflicts(indexX, ...indexY) {
3531
- return indexY.map((y) => parser3(indexX, y, (result, file) => append(result.conflicted, file)));
3531
+ return indexY.map((y) => parser3(indexX, y, (result, file) => result.conflicted.push(file)));
3532
3532
  }
3533
3533
  function splitLine(result, lineStr) {
3534
3534
  const trimmed2 = lineStr.trim();
3535
3535
  switch (" ") {
3536
3536
  case trimmed2.charAt(2):
3537
- return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.substr(3));
3537
+ return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.slice(3));
3538
3538
  case trimmed2.charAt(1):
3539
- return data(" ", trimmed2.charAt(0), trimmed2.substr(2));
3539
+ return data(" ", trimmed2.charAt(0), trimmed2.slice(2));
3540
3540
  default:
3541
3541
  return;
3542
3542
  }
@@ -3584,58 +3584,54 @@ var init_StatusSummary = __esm({
3584
3584
  parser3(
3585
3585
  " ",
3586
3586
  "A",
3587
- (result, file) => append(result.created, file)
3587
+ (result, file) => result.created.push(file)
3588
3588
  ),
3589
3589
  parser3(
3590
3590
  " ",
3591
3591
  "D",
3592
- (result, file) => append(result.deleted, file)
3592
+ (result, file) => result.deleted.push(file)
3593
3593
  ),
3594
3594
  parser3(
3595
3595
  " ",
3596
3596
  "M",
3597
- (result, file) => append(result.modified, file)
3598
- ),
3599
- parser3(
3600
- "A",
3601
- " ",
3602
- (result, file) => append(result.created, file) && append(result.staged, file)
3603
- ),
3604
- parser3(
3605
- "A",
3606
- "M",
3607
- (result, file) => append(result.created, file) && append(result.staged, file) && append(result.modified, file)
3608
- ),
3609
- parser3(
3610
- "D",
3611
- " ",
3612
- (result, file) => append(result.deleted, file) && append(result.staged, file)
3613
- ),
3614
- parser3(
3615
- "M",
3616
- " ",
3617
- (result, file) => append(result.modified, file) && append(result.staged, file)
3618
- ),
3619
- parser3(
3620
- "M",
3621
- "M",
3622
- (result, file) => append(result.modified, file) && append(result.staged, file)
3597
+ (result, file) => result.modified.push(file)
3623
3598
  ),
3599
+ parser3("A", " ", (result, file) => {
3600
+ result.created.push(file);
3601
+ result.staged.push(file);
3602
+ }),
3603
+ parser3("A", "M", (result, file) => {
3604
+ result.created.push(file);
3605
+ result.staged.push(file);
3606
+ result.modified.push(file);
3607
+ }),
3608
+ parser3("D", " ", (result, file) => {
3609
+ result.deleted.push(file);
3610
+ result.staged.push(file);
3611
+ }),
3612
+ parser3("M", " ", (result, file) => {
3613
+ result.modified.push(file);
3614
+ result.staged.push(file);
3615
+ }),
3616
+ parser3("M", "M", (result, file) => {
3617
+ result.modified.push(file);
3618
+ result.staged.push(file);
3619
+ }),
3624
3620
  parser3("R", " ", (result, file) => {
3625
- append(result.renamed, renamedFile(file));
3621
+ result.renamed.push(renamedFile(file));
3626
3622
  }),
3627
3623
  parser3("R", "M", (result, file) => {
3628
3624
  const renamed = renamedFile(file);
3629
- append(result.renamed, renamed);
3630
- append(result.modified, renamed.to);
3625
+ result.renamed.push(renamed);
3626
+ result.modified.push(renamed.to);
3631
3627
  }),
3632
3628
  parser3("!", "!", (_result, _file) => {
3633
- append(_result.ignored = _result.ignored || [], _file);
3629
+ (_result.ignored = _result.ignored || []).push(_file);
3634
3630
  }),
3635
3631
  parser3(
3636
3632
  "?",
3637
3633
  "?",
3638
- (result, file) => append(result.not_added, file)
3634
+ (result, file) => result.not_added.push(file)
3639
3635
  ),
3640
3636
  ...conflicts(
3641
3637
  "A",
@@ -3793,6 +3789,48 @@ var init_version = __esm({
3793
3789
  ];
3794
3790
  }
3795
3791
  });
3792
+ function createCloneTask(api, task, repoPath, ...args) {
3793
+ if (!filterString(repoPath)) {
3794
+ return configurationErrorTask(`git.${api}() requires a string 'repoPath'`);
3795
+ }
3796
+ return task(repoPath, filterType(args[0], filterString), getTrailingOptions(arguments));
3797
+ }
3798
+ function clone_default() {
3799
+ return {
3800
+ clone(repo, ...rest) {
3801
+ return this._runTask(
3802
+ createCloneTask("clone", cloneTask, filterType(repo, filterString), ...rest),
3803
+ trailingFunctionArgument(arguments)
3804
+ );
3805
+ },
3806
+ mirror(repo, ...rest) {
3807
+ return this._runTask(
3808
+ createCloneTask("mirror", cloneMirrorTask, filterType(repo, filterString), ...rest),
3809
+ trailingFunctionArgument(arguments)
3810
+ );
3811
+ }
3812
+ };
3813
+ }
3814
+ var cloneTask;
3815
+ var cloneMirrorTask;
3816
+ var init_clone = __esm({
3817
+ "src/lib/tasks/clone.ts"() {
3818
+ "use strict";
3819
+ init_task();
3820
+ init_utils();
3821
+ init_pathspec();
3822
+ cloneTask = (repo, directory, customArgs) => {
3823
+ const commands = ["clone", ...customArgs];
3824
+ filterString(repo) && commands.push(pathspec(repo));
3825
+ filterString(directory) && commands.push(pathspec(directory));
3826
+ return straightThroughStringTask(commands);
3827
+ };
3828
+ cloneMirrorTask = (repo, directory, customArgs) => {
3829
+ append(customArgs, "--mirror");
3830
+ return cloneTask(repo, directory, customArgs);
3831
+ };
3832
+ }
3833
+ });
3796
3834
  var simple_git_api_exports = {};
3797
3835
  __export2(simple_git_api_exports, {
3798
3836
  SimpleGitApi: () => SimpleGitApi
@@ -3819,6 +3857,7 @@ var init_simple_git_api = __esm({
3819
3857
  init_task();
3820
3858
  init_version();
3821
3859
  init_utils();
3860
+ init_clone();
3822
3861
  SimpleGitApi = class {
3823
3862
  constructor(_executor) {
3824
3863
  this._executor = _executor;
@@ -3921,6 +3960,7 @@ var init_simple_git_api = __esm({
3921
3960
  Object.assign(
3922
3961
  SimpleGitApi.prototype,
3923
3962
  checkout_default(),
3963
+ clone_default(),
3924
3964
  commit_default(),
3925
3965
  config_default(),
3926
3966
  count_objects_default(),
@@ -4244,35 +4284,6 @@ var init_check_ignore = __esm({
4244
4284
  init_CheckIgnore();
4245
4285
  }
4246
4286
  });
4247
- var clone_exports = {};
4248
- __export2(clone_exports, {
4249
- cloneMirrorTask: () => cloneMirrorTask,
4250
- cloneTask: () => cloneTask
4251
- });
4252
- function disallowedCommand(command) {
4253
- return /^--upload-pack(=|$)/.test(command);
4254
- }
4255
- function cloneTask(repo, directory, customArgs) {
4256
- const commands = ["clone", ...customArgs];
4257
- filterString(repo) && commands.push(repo);
4258
- filterString(directory) && commands.push(directory);
4259
- const banned = commands.find(disallowedCommand);
4260
- if (banned) {
4261
- return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
4262
- }
4263
- return straightThroughStringTask(commands);
4264
- }
4265
- function cloneMirrorTask(repo, directory, customArgs) {
4266
- append(customArgs, "--mirror");
4267
- return cloneTask(repo, directory, customArgs);
4268
- }
4269
- var init_clone = __esm({
4270
- "src/lib/tasks/clone.ts"() {
4271
- "use strict";
4272
- init_task();
4273
- init_utils();
4274
- }
4275
- });
4276
4287
  function parseFetchResult(stdOut, stdErr) {
4277
4288
  const result = {
4278
4289
  raw: stdOut,
@@ -4328,7 +4339,7 @@ var fetch_exports = {};
4328
4339
  __export2(fetch_exports, {
4329
4340
  fetchTask: () => fetchTask
4330
4341
  });
4331
- function disallowedCommand2(command) {
4342
+ function disallowedCommand(command) {
4332
4343
  return /^--upload-pack(=|$)/.test(command);
4333
4344
  }
4334
4345
  function fetchTask(remote, branch, customArgs) {
@@ -4336,7 +4347,7 @@ function fetchTask(remote, branch, customArgs) {
4336
4347
  if (remote && branch) {
4337
4348
  commands.push(remote, branch);
4338
4349
  }
4339
- const banned = commands.find(disallowedCommand2);
4350
+ const banned = commands.find(disallowedCommand);
4340
4351
  if (banned) {
4341
4352
  return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
4342
4353
  }
@@ -4652,7 +4663,7 @@ var require_git = __commonJS2({
4652
4663
  var { GitExecutor: GitExecutor2 } = (init_git_executor(), __toCommonJS2(git_executor_exports));
4653
4664
  var { SimpleGitApi: SimpleGitApi2 } = (init_simple_git_api(), __toCommonJS2(simple_git_api_exports));
4654
4665
  var { Scheduler: Scheduler2 } = (init_scheduler(), __toCommonJS2(scheduler_exports));
4655
- var { configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS2(task_exports));
4666
+ var { adhocExecTask: adhocExecTask2, configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS2(task_exports));
4656
4667
  var {
4657
4668
  asArray: asArray2,
4658
4669
  filterArray: filterArray2,
@@ -4673,7 +4684,6 @@ var require_git = __commonJS2({
4673
4684
  } = (init_branch(), __toCommonJS2(branch_exports));
4674
4685
  var { checkIgnoreTask: checkIgnoreTask2 } = (init_check_ignore(), __toCommonJS2(check_ignore_exports));
4675
4686
  var { checkIsRepoTask: checkIsRepoTask2 } = (init_check_is_repo(), __toCommonJS2(check_is_repo_exports));
4676
- var { cloneTask: cloneTask2, cloneMirrorTask: cloneMirrorTask2 } = (init_clone(), __toCommonJS2(clone_exports));
4677
4687
  var { cleanWithOptionsTask: cleanWithOptionsTask2, isCleanOptionsArray: isCleanOptionsArray2 } = (init_clean(), __toCommonJS2(clean_exports));
4678
4688
  var { diffSummaryTask: diffSummaryTask2 } = (init_diff(), __toCommonJS2(diff_exports));
4679
4689
  var { fetchTask: fetchTask2 } = (init_fetch(), __toCommonJS2(fetch_exports));
@@ -4728,24 +4738,6 @@ var require_git = __commonJS2({
4728
4738
  trailingFunctionArgument2(arguments)
4729
4739
  );
4730
4740
  };
4731
- function createCloneTask(api, task, repoPath, localPath) {
4732
- if (typeof repoPath !== "string") {
4733
- return configurationErrorTask2(`git.${api}() requires a string 'repoPath'`);
4734
- }
4735
- return task(repoPath, filterType2(localPath, filterString2), getTrailingOptions2(arguments));
4736
- }
4737
- Git2.prototype.clone = function() {
4738
- return this._runTask(
4739
- createCloneTask("clone", cloneTask2, ...arguments),
4740
- trailingFunctionArgument2(arguments)
4741
- );
4742
- };
4743
- Git2.prototype.mirror = function() {
4744
- return this._runTask(
4745
- createCloneTask("mirror", cloneMirrorTask2, ...arguments),
4746
- trailingFunctionArgument2(arguments)
4747
- );
4748
- };
4749
4741
  Git2.prototype.mv = function(from, to) {
4750
4742
  return this._runTask(moveTask2(from, to), trailingFunctionArgument2(arguments));
4751
4743
  };
@@ -4778,10 +4770,13 @@ var require_git = __commonJS2({
4778
4770
  );
4779
4771
  };
4780
4772
  Git2.prototype.silent = function(silence) {
4781
- console.warn(
4782
- "simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this will be an error in version 3"
4773
+ return this._runTask(
4774
+ adhocExecTask2(
4775
+ () => console.warn(
4776
+ "simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this method will be removed."
4777
+ )
4778
+ )
4783
4779
  );
4784
- return this;
4785
4780
  };
4786
4781
  Git2.prototype.tags = function(options, then) {
4787
4782
  return this._runTask(
@@ -5007,7 +5002,13 @@ var require_git = __commonJS2({
5007
5002
  return this._runTask(task);
5008
5003
  };
5009
5004
  Git2.prototype.clearQueue = function() {
5010
- return this;
5005
+ return this._runTask(
5006
+ adhocExecTask2(
5007
+ () => console.warn(
5008
+ "simple-git deprecation notice: clearQueue() is deprecated and will be removed, switch to using the abortPlugin instead."
5009
+ )
5010
+ )
5011
+ );
5011
5012
  };
5012
5013
  Git2.prototype.checkIgnore = function(pathnames, then) {
5013
5014
  return this._runTask(
@@ -5077,19 +5078,36 @@ function abortPlugin(signal) {
5077
5078
  function isConfigSwitch(arg) {
5078
5079
  return typeof arg === "string" && arg.trim().toLowerCase() === "-c";
5079
5080
  }
5080
- function preventProtocolOverride(arg, next) {
5081
- if (!isConfigSwitch(arg)) {
5082
- return;
5083
- }
5084
- if (!/^\s*protocol(.[a-z]+)?.allow/.test(next)) {
5085
- return;
5081
+ function isCloneUploadPackSwitch(char, arg) {
5082
+ if (typeof arg !== "string" || !arg.includes(char)) {
5083
+ return false;
5086
5084
  }
5087
- throw new GitPluginError(
5088
- void 0,
5089
- "unsafe",
5090
- "Configuring protocol.allow is not permitted without enabling allowUnsafeExtProtocol"
5091
- );
5085
+ const cleaned = arg.trim().replace(/\0/g, "");
5086
+ return /^(--no)?-{1,2}[\dlsqvnobucj]+(\s|$)/.test(cleaned);
5087
+ }
5088
+ function preventConfigBuilder(config, setting, message = String(config)) {
5089
+ const regex = typeof config === "string" ? new RegExp(`\\s*${config}`, "i") : config;
5090
+ return function preventCommand(options, arg, next) {
5091
+ if (options[setting] !== true && isConfigSwitch(arg) && regex.test(next)) {
5092
+ throw new GitPluginError(
5093
+ void 0,
5094
+ "unsafe",
5095
+ `Configuring ${message} is not permitted without enabling ${setting}`
5096
+ );
5097
+ }
5098
+ };
5092
5099
  }
5100
+ var preventUnsafeConfig = [
5101
+ preventConfigBuilder(
5102
+ /^\s*protocol(.[a-z]+)?.allow/i,
5103
+ "allowUnsafeProtocolOverride",
5104
+ "protocol.allow"
5105
+ ),
5106
+ preventConfigBuilder("core.sshCommand", "allowUnsafeSshCommand"),
5107
+ preventConfigBuilder("core.gitProxy", "allowUnsafeGitProxy"),
5108
+ preventConfigBuilder("core.hooksPath", "allowUnsafeHooksPath"),
5109
+ preventConfigBuilder("diff.external", "allowUnsafeDiffExternal")
5110
+ ];
5093
5111
  function preventUploadPack(arg, method) {
5094
5112
  if (/^\s*--(upload|receive)-pack/.test(arg)) {
5095
5113
  throw new GitPluginError(
@@ -5098,7 +5116,7 @@ function preventUploadPack(arg, method) {
5098
5116
  `Use of --upload-pack or --receive-pack is not permitted without enabling allowUnsafePack`
5099
5117
  );
5100
5118
  }
5101
- if (method === "clone" && /^\s*-u\b/.test(arg)) {
5119
+ if (method === "clone" && isCloneUploadPackSwitch("u", arg)) {
5102
5120
  throw new GitPluginError(
5103
5121
  void 0,
5104
5122
  "unsafe",
@@ -5114,16 +5132,16 @@ function preventUploadPack(arg, method) {
5114
5132
  }
5115
5133
  }
5116
5134
  function blockUnsafeOperationsPlugin({
5117
- allowUnsafeProtocolOverride = false,
5118
- allowUnsafePack = false
5135
+ allowUnsafePack = false,
5136
+ ...options
5119
5137
  } = {}) {
5120
5138
  return {
5121
5139
  type: "spawn.args",
5122
5140
  action(args, context) {
5123
5141
  args.forEach((current, index) => {
5124
5142
  const next = index < args.length ? args[index + 1] : "";
5125
- allowUnsafeProtocolOverride || preventProtocolOverride(current, next);
5126
5143
  allowUnsafePack || preventUploadPack(current, context.method);
5144
+ preventUnsafeConfig.forEach((helper) => helper(options, current, next));
5127
5145
  });
5128
5146
  return args;
5129
5147
  }
@@ -5207,7 +5225,7 @@ init_utils();
5207
5225
  var WRONG_NUMBER_ERR = `Invalid value supplied for custom binary, requires a single string or an array containing either one or two strings`;
5208
5226
  var WRONG_CHARS_ERR = `Invalid value supplied for custom binary, restricted characters must be removed or supply the unsafe.allowUnsafeCustomBinary option`;
5209
5227
  function isBadArgument(arg) {
5210
- return !arg || !/^([a-z]:)?([a-z0-9/.\\_-]+)$/i.test(arg);
5228
+ return !arg || !/^([a-z]:)?([a-z0-9/.\\_~-]+)$/i.test(arg);
5211
5229
  }
5212
5230
  function toBinaryConfig(input, allowUnsafe) {
5213
5231
  if (input.length < 1 || input.length > 2) {
@@ -5435,12 +5453,12 @@ function gitInstanceFactory(baseDir, options) {
5435
5453
  plugins.add(commandConfigPrefixingPlugin(config.config));
5436
5454
  }
5437
5455
  plugins.add(blockUnsafeOperationsPlugin(config.unsafe));
5438
- plugins.add(suffixPathsPlugin());
5439
5456
  plugins.add(completionDetectionPlugin(config.completion));
5440
5457
  config.abort && plugins.add(abortPlugin(config.abort));
5441
5458
  config.progress && plugins.add(progressMonitorPlugin(config.progress));
5442
5459
  config.timeout && plugins.add(timeoutPlugin(config.timeout));
5443
5460
  config.spawnOptions && plugins.add(spawnOptionsPlugin(config.spawnOptions));
5461
+ plugins.add(suffixPathsPlugin());
5444
5462
  plugins.add(errorDetectionPlugin(errorDetectionHandler(true)));
5445
5463
  config.errors && plugins.add(errorDetectionPlugin(config.errors));
5446
5464
  customBinaryPlugin(plugins, config.binary, config.unsafe?.allowUnsafeCustomBinary);
@@ -5748,6 +5766,21 @@ async function doesPathExist(filepath) {
5748
5766
  }
5749
5767
  }
5750
5768
 
5769
+ // ../commons/core-utils/lib/extractErrorMessage.js
5770
+ function extractErrorMessage(e) {
5771
+ if (typeof e === "string") {
5772
+ return e.length > 0 ? e : "Unknown error";
5773
+ }
5774
+ if (e instanceof Error) {
5775
+ return e.message.length > 0 ? e.message : "Unknown error";
5776
+ }
5777
+ if (typeof e === "object" && e !== null && "message" in e && typeof e["message"] === "string") {
5778
+ return e["message"].length > 0 ? e["message"] : "Unknown error";
5779
+ }
5780
+ const stringified = String(e);
5781
+ return stringified.length > 0 ? stringified : "Unknown error";
5782
+ }
5783
+
5751
5784
  // ../commons/github/lib/cloneRepository.js
5752
5785
  var import_child_process2 = require("child_process");
5753
5786
  var import_tmp_promise = __toESM(require("tmp-promise"), 1);
@@ -5769,7 +5802,7 @@ function parseRepository(githubRepository) {
5769
5802
  } else if (parts.length === 3 && parts[0] != null && parts[1] != null && parts[2] != null) {
5770
5803
  [remote, owner, repo] = parts;
5771
5804
  } else {
5772
- throw new Error(`Failed to parse GitHub repostiory ${githubRepository}`);
5805
+ throw new Error(`Failed to parse GitHub repository ${githubRepository}`);
5773
5806
  }
5774
5807
  return newRepositoryReference({ remote, owner, repo });
5775
5808
  }
@@ -5850,7 +5883,7 @@ async function cloneRepository({ githubRepository, installationToken, targetDire
5850
5883
  await git.clone(cloneUrl, ".");
5851
5884
  } catch (error) {
5852
5885
  const elapsed = Date.now() - startTime;
5853
- const errorMessage = error instanceof Error ? error.message : String(error);
5886
+ const errorMessage = extractErrorMessage(error);
5854
5887
  if (errorMessage.includes("ENOENT") || errorMessage.includes("spawn git")) {
5855
5888
  const diagnostics = getGitDiagnostics();
5856
5889
  throw new Error(`Failed to clone repository: git command not found. Self-hosted GitHub mode requires git to be installed on the host machine where the Fern CLI runs. URL: ${sanitizedUrl}. Elapsed: ${elapsed}ms. Debug info: ${diagnostics}. Original error: ${errorMessage}`);
@@ -8922,7 +8955,7 @@ var ReadmeGenerator = class {
8922
8955
  await writer.writeLine();
8923
8956
  await writer.writeLine("```groovy");
8924
8957
  await writer.writeLine("dependencies {");
8925
- await writer.writeLine(` implementation '${maven.group}:${maven.artifact}'`);
8958
+ await writer.writeLine(` implementation '${maven.group}:${maven.artifact}:${maven.version}'`);
8926
8959
  await writer.writeLine("}");
8927
8960
  await writer.writeLine("```");
8928
8961
  await writer.writeLine();
@@ -9735,7 +9768,7 @@ async function findExistingUpdatablePR(octokit, owner, repo, baseBranch, logger)
9735
9768
  }
9736
9769
  return void 0;
9737
9770
  } catch (error) {
9738
- logger.debug(`Error finding existing PRs: ${error instanceof Error ? error.message : String(error)}`);
9771
+ logger.debug(`Error finding existing PRs: ${extractErrorMessage(error)}`);
9739
9772
  return void 0;
9740
9773
  }
9741
9774
  }
@@ -9762,16 +9795,22 @@ async function checkPRHasOnlyGenerationCommits(octokit, owner, repo, pullNumber,
9762
9795
  }
9763
9796
  return true;
9764
9797
  } catch (error) {
9765
- logger.debug(`Error checking PR commits: ${error instanceof Error ? error.message : String(error)}`);
9798
+ logger.debug(`Error checking PR commits: ${extractErrorMessage(error)}`);
9766
9799
  return false;
9767
9800
  }
9768
9801
  }
9769
9802
 
9770
9803
  // src/pipeline/github/parseCommitMessage.ts
9771
- function parseCommitMessageForPR(commitMessage) {
9804
+ function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason) {
9772
9805
  const lines = commitMessage.split("\n");
9773
9806
  const prTitle = lines[0]?.trim() || "SDK Generation";
9774
- const prBody = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
9807
+ const bodyFromCommit = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
9808
+ let prBody = prDescription?.trim() || changelogEntry?.trim() || bodyFromCommit;
9809
+ if (versionBumpReason?.trim()) {
9810
+ prBody = `**Version Bump:** ${versionBumpReason.trim()}
9811
+
9812
+ ${prBody}`;
9813
+ }
9775
9814
  return { prTitle, prBody };
9776
9815
  }
9777
9816
 
@@ -10031,14 +10070,17 @@ var GithubStep = class extends BaseStep {
10031
10070
  this.logger.debug(`Pushed ${tagName} tag for generation tracking`);
10032
10071
  result.generationBaseTagSha = generationBaseSha;
10033
10072
  } catch (error) {
10034
- this.logger.debug(
10035
- `Could not push generation tag: ${error instanceof Error ? error.message : String(error)}`
10036
- );
10073
+ this.logger.debug(`Could not push generation tag: ${extractErrorMessage(error)}`);
10037
10074
  }
10038
10075
  }
10039
10076
  }
10040
10077
  const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
10041
- const { prTitle, prBody } = parseCommitMessageForPR(finalCommitMessage);
10078
+ const { prTitle, prBody } = parseCommitMessageForPR(
10079
+ finalCommitMessage,
10080
+ this.config.changelogEntry,
10081
+ this.config.prDescription,
10082
+ this.config.versionBumpReason
10083
+ );
10042
10084
  const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
10043
10085
  const enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
10044
10086
  if (isUpdatingExistingPR && existingPR != null) {
@@ -10055,9 +10097,7 @@ var GithubStep = class extends BaseStep {
10055
10097
  });
10056
10098
  this.logger.debug(`Updated PR #${existingPR.number} title and body`);
10057
10099
  } catch (error) {
10058
- this.logger.debug(
10059
- `Failed to update PR title/body: ${error instanceof Error ? error.message : String(error)}`
10060
- );
10100
+ this.logger.debug(`Failed to update PR title/body: ${extractErrorMessage(error)}`);
10061
10101
  }
10062
10102
  } else {
10063
10103
  const head = `${owner}:${prBranch}`;
@@ -10074,7 +10114,7 @@ var GithubStep = class extends BaseStep {
10074
10114
  result.prUrl = pullRequest.html_url;
10075
10115
  result.prNumber = pullRequest.number;
10076
10116
  } catch (error) {
10077
- const message = error instanceof Error ? error.message : String(error);
10117
+ const message = extractErrorMessage(error);
10078
10118
  if (message.includes("A pull request already exists for")) {
10079
10119
  this.logger.warn(`A pull request already exists for ${head}`);
10080
10120
  } else {
@@ -10440,7 +10480,7 @@ var PostGenerationPipeline = class {
10440
10480
  } catch (error) {
10441
10481
  result.success = false;
10442
10482
  result.errors = result.errors ?? [];
10443
- const errorMessage = error instanceof Error ? error.message : String(error);
10483
+ const errorMessage = extractErrorMessage(error);
10444
10484
  result.errors.push(`${step.name} step error: ${errorMessage}`);
10445
10485
  }
10446
10486
  }
package/dist/cli.js CHANGED
@@ -7678,7 +7678,7 @@ var require_dist2 = __commonJS({
7678
7678
  }
7679
7679
  });
7680
7680
 
7681
- // ../../node_modules/.pnpm/simple-git@3.30.0/node_modules/simple-git/dist/esm/index.js
7681
+ // ../../node_modules/.pnpm/simple-git@3.33.0/node_modules/simple-git/dist/esm/index.js
7682
7682
  function pathspec(...paths) {
7683
7683
  const key = new String(paths);
7684
7684
  cache.set(key, paths);
@@ -8778,15 +8778,15 @@ function parser3(indexX, indexY, handler2) {
8778
8778
  return [`${indexX}${indexY}`, handler2];
8779
8779
  }
8780
8780
  function conflicts(indexX, ...indexY) {
8781
- return indexY.map((y) => parser3(indexX, y, (result, file) => append(result.conflicted, file)));
8781
+ return indexY.map((y) => parser3(indexX, y, (result, file) => result.conflicted.push(file)));
8782
8782
  }
8783
8783
  function splitLine(result, lineStr) {
8784
8784
  const trimmed2 = lineStr.trim();
8785
8785
  switch (" ") {
8786
8786
  case trimmed2.charAt(2):
8787
- return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.substr(3));
8787
+ return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.slice(3));
8788
8788
  case trimmed2.charAt(1):
8789
- return data(" ", trimmed2.charAt(0), trimmed2.substr(2));
8789
+ return data(" ", trimmed2.charAt(0), trimmed2.slice(2));
8790
8790
  default:
8791
8791
  return;
8792
8792
  }
@@ -8863,6 +8863,28 @@ function versionParser(stdOut) {
8863
8863
  }
8864
8864
  return parseStringResponse(versionResponse(0, 0, 0, stdOut), parsers7, stdOut);
8865
8865
  }
8866
+ function createCloneTask(api, task, repoPath, ...args) {
8867
+ if (!filterString(repoPath)) {
8868
+ return configurationErrorTask(`git.${api}() requires a string 'repoPath'`);
8869
+ }
8870
+ return task(repoPath, filterType(args[0], filterString), getTrailingOptions(arguments));
8871
+ }
8872
+ function clone_default() {
8873
+ return {
8874
+ clone(repo, ...rest) {
8875
+ return this._runTask(
8876
+ createCloneTask("clone", cloneTask, filterType(repo, filterString), ...rest),
8877
+ trailingFunctionArgument(arguments)
8878
+ );
8879
+ },
8880
+ mirror(repo, ...rest) {
8881
+ return this._runTask(
8882
+ createCloneTask("mirror", cloneMirrorTask, filterType(repo, filterString), ...rest),
8883
+ trailingFunctionArgument(arguments)
8884
+ );
8885
+ }
8886
+ };
8887
+ }
8866
8888
  function applyPatchTask(patches, customArgs) {
8867
8889
  return straightThroughStringTask(["apply", ...customArgs, ...patches]);
8868
8890
  }
@@ -8972,23 +8994,6 @@ function checkIgnoreTask(paths) {
8972
8994
  parser: parseCheckIgnore
8973
8995
  };
8974
8996
  }
8975
- function disallowedCommand(command) {
8976
- return /^--upload-pack(=|$)/.test(command);
8977
- }
8978
- function cloneTask(repo, directory, customArgs) {
8979
- const commands = ["clone", ...customArgs];
8980
- filterString(repo) && commands.push(repo);
8981
- filterString(directory) && commands.push(directory);
8982
- const banned = commands.find(disallowedCommand);
8983
- if (banned) {
8984
- return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
8985
- }
8986
- return straightThroughStringTask(commands);
8987
- }
8988
- function cloneMirrorTask(repo, directory, customArgs) {
8989
- append(customArgs, "--mirror");
8990
- return cloneTask(repo, directory, customArgs);
8991
- }
8992
8997
  function parseFetchResult(stdOut, stdErr) {
8993
8998
  const result = {
8994
8999
  raw: stdOut,
@@ -9000,7 +9005,7 @@ function parseFetchResult(stdOut, stdErr) {
9000
9005
  };
9001
9006
  return parseStringResponse(result, parsers10, [stdOut, stdErr]);
9002
9007
  }
9003
- function disallowedCommand2(command) {
9008
+ function disallowedCommand(command) {
9004
9009
  return /^--upload-pack(=|$)/.test(command);
9005
9010
  }
9006
9011
  function fetchTask(remote, branch, customArgs) {
@@ -9008,7 +9013,7 @@ function fetchTask(remote, branch, customArgs) {
9008
9013
  if (remote && branch) {
9009
9014
  commands.push(remote, branch);
9010
9015
  }
9011
- const banned = commands.find(disallowedCommand2);
9016
+ const banned = commands.find(disallowedCommand);
9012
9017
  if (banned) {
9013
9018
  return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
9014
9019
  }
@@ -9210,18 +9215,24 @@ function abortPlugin(signal) {
9210
9215
  function isConfigSwitch(arg) {
9211
9216
  return typeof arg === "string" && arg.trim().toLowerCase() === "-c";
9212
9217
  }
9213
- function preventProtocolOverride(arg, next) {
9214
- if (!isConfigSwitch(arg)) {
9215
- return;
9216
- }
9217
- if (!/^\s*protocol(.[a-z]+)?.allow/.test(next)) {
9218
- return;
9218
+ function isCloneUploadPackSwitch(char, arg) {
9219
+ if (typeof arg !== "string" || !arg.includes(char)) {
9220
+ return false;
9219
9221
  }
9220
- throw new GitPluginError(
9221
- void 0,
9222
- "unsafe",
9223
- "Configuring protocol.allow is not permitted without enabling allowUnsafeExtProtocol"
9224
- );
9222
+ const cleaned = arg.trim().replace(/\0/g, "");
9223
+ return /^(--no)?-{1,2}[\dlsqvnobucj]+(\s|$)/.test(cleaned);
9224
+ }
9225
+ function preventConfigBuilder(config, setting, message = String(config)) {
9226
+ const regex = typeof config === "string" ? new RegExp(`\\s*${config}`, "i") : config;
9227
+ return function preventCommand(options, arg, next) {
9228
+ if (options[setting] !== true && isConfigSwitch(arg) && regex.test(next)) {
9229
+ throw new GitPluginError(
9230
+ void 0,
9231
+ "unsafe",
9232
+ `Configuring ${message} is not permitted without enabling ${setting}`
9233
+ );
9234
+ }
9235
+ };
9225
9236
  }
9226
9237
  function preventUploadPack(arg, method) {
9227
9238
  if (/^\s*--(upload|receive)-pack/.test(arg)) {
@@ -9231,7 +9242,7 @@ function preventUploadPack(arg, method) {
9231
9242
  `Use of --upload-pack or --receive-pack is not permitted without enabling allowUnsafePack`
9232
9243
  );
9233
9244
  }
9234
- if (method === "clone" && /^\s*-u\b/.test(arg)) {
9245
+ if (method === "clone" && isCloneUploadPackSwitch("u", arg)) {
9235
9246
  throw new GitPluginError(
9236
9247
  void 0,
9237
9248
  "unsafe",
@@ -9247,16 +9258,16 @@ function preventUploadPack(arg, method) {
9247
9258
  }
9248
9259
  }
9249
9260
  function blockUnsafeOperationsPlugin({
9250
- allowUnsafeProtocolOverride = false,
9251
- allowUnsafePack = false
9261
+ allowUnsafePack = false,
9262
+ ...options
9252
9263
  } = {}) {
9253
9264
  return {
9254
9265
  type: "spawn.args",
9255
9266
  action(args, context) {
9256
9267
  args.forEach((current, index) => {
9257
9268
  const next = index < args.length ? args[index + 1] : "";
9258
- allowUnsafeProtocolOverride || preventProtocolOverride(current, next);
9259
9269
  allowUnsafePack || preventUploadPack(current, context.method);
9270
+ preventUnsafeConfig.forEach((helper) => helper(options, current, next));
9260
9271
  });
9261
9272
  return args;
9262
9273
  }
@@ -9334,7 +9345,7 @@ function completionDetectionPlugin({
9334
9345
  };
9335
9346
  }
9336
9347
  function isBadArgument(arg) {
9337
- return !arg || !/^([a-z]:)?([a-z0-9/.\\_-]+)$/i.test(arg);
9348
+ return !arg || !/^([a-z]:)?([a-z0-9/.\\_~-]+)$/i.test(arg);
9338
9349
  }
9339
9350
  function toBinaryConfig(input, allowUnsafe) {
9340
9351
  if (input.length < 1 || input.length > 2) {
@@ -9522,20 +9533,20 @@ function gitInstanceFactory(baseDir, options) {
9522
9533
  plugins.add(commandConfigPrefixingPlugin(config.config));
9523
9534
  }
9524
9535
  plugins.add(blockUnsafeOperationsPlugin(config.unsafe));
9525
- plugins.add(suffixPathsPlugin());
9526
9536
  plugins.add(completionDetectionPlugin(config.completion));
9527
9537
  config.abort && plugins.add(abortPlugin(config.abort));
9528
9538
  config.progress && plugins.add(progressMonitorPlugin(config.progress));
9529
9539
  config.timeout && plugins.add(timeoutPlugin(config.timeout));
9530
9540
  config.spawnOptions && plugins.add(spawnOptionsPlugin(config.spawnOptions));
9541
+ plugins.add(suffixPathsPlugin());
9531
9542
  plugins.add(errorDetectionPlugin(errorDetectionHandler(true)));
9532
9543
  config.errors && plugins.add(errorDetectionPlugin(config.errors));
9533
9544
  customBinaryPlugin(plugins, config.binary, config.unsafe?.allowUnsafeCustomBinary);
9534
9545
  return new Git(config, plugins);
9535
9546
  }
9536
- var import_node_buffer, import_file_exists, import_debug, import_child_process, import_promise_deferred, import_node_path, import_promise_deferred2, import_node_events, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __esm2, __commonJS2, __export2, __copyProps2, __toCommonJS, cache, init_pathspec, GitError, init_git_error, GitResponseError, init_git_response_error, TaskConfigurationError, init_task_configuration_error, NULL, NOOP, objectToString, init_util, filterArray, filterNumber, filterString, filterStringOrStringArray, filterHasLength, init_argument_filters, ExitCodes, init_exit_codes, GitOutputStreams, init_git_output_streams, LineParser, RemoteLineParser, init_line_parser, defaultOptions, init_simple_git_options, init_task_options, init_task_parser, utils_exports, init_utils, check_is_repo_exports, CheckRepoActions, onError, parser2, init_check_is_repo, CleanResponse, removalRegexp, dryRunRemovalRegexp, isFolderRegexp, init_CleanSummary, task_exports, EMPTY_COMMANDS, init_task, clean_exports, CONFIG_ERROR_INTERACTIVE_MODE, CONFIG_ERROR_MODE_REQUIRED, CONFIG_ERROR_UNKNOWN_OPTION, CleanOptions, CleanOptionValues, init_clean, ConfigList, init_ConfigList, GitConfigScope, init_config, DiffNameStatus, diffNameStatus, init_diff_name_status, disallowedOptions, Query, _a3, GrepQuery, init_grep, reset_exports, ResetMode, validResetModes, init_reset, init_git_logger, TasksPendingQueue, init_tasks_pending_queue, GitExecutorChain, init_git_executor_chain, git_executor_exports, GitExecutor, init_git_executor, init_task_callback, init_change_working_directory, init_checkout, parser22, init_count_objects, parsers, init_parse_commit, init_commit, init_first_commit, init_hash_object, InitSummary, initResponseRegex, reInitResponseRegex, init_InitSummary, bareCommand, init_init, logFormatRegex, init_log_format, DiffSummary, init_DiffSummary, statParser, numStatParser, nameOnlyParser, nameStatusParser, diffSummaryParsers, init_parse_diff_summary, START_BOUNDARY, COMMIT_BOUNDARY, SPLITTER, defaultFieldNames, init_parse_list_log_summary, diff_exports, init_diff, excludeOptions, init_log, MergeSummaryConflict, MergeSummaryDetail, init_MergeSummary, PullSummary, PullFailedSummary, init_PullSummary, remoteMessagesObjectParsers, init_parse_remote_objects, parsers2, RemoteMessageSummary, init_parse_remote_messages, FILE_UPDATE_REGEX, SUMMARY_REGEX, ACTION_REGEX, parsers3, errorParsers, parsePullDetail, parsePullResult, init_parse_pull, parsers4, parseMergeResult, parseMergeDetail, init_parse_merge, init_merge, parsers5, parsePushResult, parsePushDetail, init_parse_push, push_exports, init_push, init_show, fromPathRegex, FileStatusSummary, init_FileStatusSummary, StatusSummary, parsers6, parseStatusSummary, init_StatusSummary, ignoredOptions, init_status, NOT_INSTALLED, parsers7, init_version, simple_git_api_exports, SimpleGitApi, init_simple_git_api, scheduler_exports, createScheduledTask, Scheduler, init_scheduler, apply_patch_exports, init_apply_patch, BranchDeletionBatch, init_BranchDeleteSummary, deleteSuccessRegex, deleteErrorRegex, parsers8, parseBranchDeletions, init_parse_branch_delete, BranchSummaryResult, init_BranchSummary, parsers9, currentBranchParser, init_parse_branch, branch_exports, init_branch, parseCheckIgnore, init_CheckIgnore, check_ignore_exports, init_check_ignore, clone_exports, init_clone, parsers10, init_parse_fetch, fetch_exports, init_fetch, parsers11, init_parse_move, move_exports, init_move, pull_exports, init_pull, init_GetRemoteSummary, remote_exports, init_remote, stash_list_exports, init_stash_list, sub_module_exports, init_sub_module, TagList, parseTagList, init_TagList, tag_exports, init_tag, require_git, GitConstructError, GitPluginError, never, WRONG_NUMBER_ERR, WRONG_CHARS_ERR, PluginStore, Git, simpleGit;
9547
+ var import_node_buffer, import_file_exists, import_debug, import_child_process, import_promise_deferred, import_node_path, import_promise_deferred2, import_node_events, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __esm2, __commonJS2, __export2, __copyProps2, __toCommonJS, cache, init_pathspec, GitError, init_git_error, GitResponseError, init_git_response_error, TaskConfigurationError, init_task_configuration_error, NULL, NOOP, objectToString, init_util, filterArray, filterNumber, filterString, filterStringOrStringArray, filterHasLength, init_argument_filters, ExitCodes, init_exit_codes, GitOutputStreams, init_git_output_streams, LineParser, RemoteLineParser, init_line_parser, defaultOptions, init_simple_git_options, init_task_options, init_task_parser, utils_exports, init_utils, check_is_repo_exports, CheckRepoActions, onError, parser2, init_check_is_repo, CleanResponse, removalRegexp, dryRunRemovalRegexp, isFolderRegexp, init_CleanSummary, task_exports, EMPTY_COMMANDS, init_task, clean_exports, CONFIG_ERROR_INTERACTIVE_MODE, CONFIG_ERROR_MODE_REQUIRED, CONFIG_ERROR_UNKNOWN_OPTION, CleanOptions, CleanOptionValues, init_clean, ConfigList, init_ConfigList, GitConfigScope, init_config, DiffNameStatus, diffNameStatus, init_diff_name_status, disallowedOptions, Query, _a3, GrepQuery, init_grep, reset_exports, ResetMode, validResetModes, init_reset, init_git_logger, TasksPendingQueue, init_tasks_pending_queue, GitExecutorChain, init_git_executor_chain, git_executor_exports, GitExecutor, init_git_executor, init_task_callback, init_change_working_directory, init_checkout, parser22, init_count_objects, parsers, init_parse_commit, init_commit, init_first_commit, init_hash_object, InitSummary, initResponseRegex, reInitResponseRegex, init_InitSummary, bareCommand, init_init, logFormatRegex, init_log_format, DiffSummary, init_DiffSummary, statParser, numStatParser, nameOnlyParser, nameStatusParser, diffSummaryParsers, init_parse_diff_summary, START_BOUNDARY, COMMIT_BOUNDARY, SPLITTER, defaultFieldNames, init_parse_list_log_summary, diff_exports, init_diff, excludeOptions, init_log, MergeSummaryConflict, MergeSummaryDetail, init_MergeSummary, PullSummary, PullFailedSummary, init_PullSummary, remoteMessagesObjectParsers, init_parse_remote_objects, parsers2, RemoteMessageSummary, init_parse_remote_messages, FILE_UPDATE_REGEX, SUMMARY_REGEX, ACTION_REGEX, parsers3, errorParsers, parsePullDetail, parsePullResult, init_parse_pull, parsers4, parseMergeResult, parseMergeDetail, init_parse_merge, init_merge, parsers5, parsePushResult, parsePushDetail, init_parse_push, push_exports, init_push, init_show, fromPathRegex, FileStatusSummary, init_FileStatusSummary, StatusSummary, parsers6, parseStatusSummary, init_StatusSummary, ignoredOptions, init_status, NOT_INSTALLED, parsers7, init_version, cloneTask, cloneMirrorTask, init_clone, simple_git_api_exports, SimpleGitApi, init_simple_git_api, scheduler_exports, createScheduledTask, Scheduler, init_scheduler, apply_patch_exports, init_apply_patch, BranchDeletionBatch, init_BranchDeleteSummary, deleteSuccessRegex, deleteErrorRegex, parsers8, parseBranchDeletions, init_parse_branch_delete, BranchSummaryResult, init_BranchSummary, parsers9, currentBranchParser, init_parse_branch, branch_exports, init_branch, parseCheckIgnore, init_CheckIgnore, check_ignore_exports, init_check_ignore, parsers10, init_parse_fetch, fetch_exports, init_fetch, parsers11, init_parse_move, move_exports, init_move, pull_exports, init_pull, init_GetRemoteSummary, remote_exports, init_remote, stash_list_exports, init_stash_list, sub_module_exports, init_sub_module, TagList, parseTagList, init_TagList, tag_exports, init_tag, require_git, GitConstructError, GitPluginError, preventUnsafeConfig, never, WRONG_NUMBER_ERR, WRONG_CHARS_ERR, PluginStore, Git, simpleGit;
9537
9548
  var init_esm4 = __esm({
9538
- "../../node_modules/.pnpm/simple-git@3.30.0/node_modules/simple-git/dist/esm/index.js"() {
9549
+ "../../node_modules/.pnpm/simple-git@3.33.0/node_modules/simple-git/dist/esm/index.js"() {
9539
9550
  "use strict";
9540
9551
  import_node_buffer = require("buffer");
9541
9552
  import_file_exists = __toESM(require_dist(), 1);
@@ -9631,7 +9642,7 @@ var init_esm4 = __esm({
9631
9642
  return typeof input === "number";
9632
9643
  };
9633
9644
  filterString = (input) => {
9634
- return typeof input === "string";
9645
+ return typeof input === "string" || isPathSpec(input);
9635
9646
  };
9636
9647
  filterStringOrStringArray = (input) => {
9637
9648
  return filterString(input) || Array.isArray(input) && input.every(filterString);
@@ -11010,58 +11021,54 @@ var init_esm4 = __esm({
11010
11021
  parser3(
11011
11022
  " ",
11012
11023
  "A",
11013
- (result, file) => append(result.created, file)
11014
- ),
11015
- parser3(
11016
- " ",
11017
- "D",
11018
- (result, file) => append(result.deleted, file)
11019
- ),
11020
- parser3(
11021
- " ",
11022
- "M",
11023
- (result, file) => append(result.modified, file)
11024
+ (result, file) => result.created.push(file)
11024
11025
  ),
11025
11026
  parser3(
11026
- "A",
11027
11027
  " ",
11028
- (result, file) => append(result.created, file) && append(result.staged, file)
11029
- ),
11030
- parser3(
11031
- "A",
11032
- "M",
11033
- (result, file) => append(result.created, file) && append(result.staged, file) && append(result.modified, file)
11034
- ),
11035
- parser3(
11036
11028
  "D",
11037
- " ",
11038
- (result, file) => append(result.deleted, file) && append(result.staged, file)
11029
+ (result, file) => result.deleted.push(file)
11039
11030
  ),
11040
11031
  parser3(
11041
- "M",
11042
11032
  " ",
11043
- (result, file) => append(result.modified, file) && append(result.staged, file)
11044
- ),
11045
- parser3(
11046
- "M",
11047
11033
  "M",
11048
- (result, file) => append(result.modified, file) && append(result.staged, file)
11034
+ (result, file) => result.modified.push(file)
11049
11035
  ),
11036
+ parser3("A", " ", (result, file) => {
11037
+ result.created.push(file);
11038
+ result.staged.push(file);
11039
+ }),
11040
+ parser3("A", "M", (result, file) => {
11041
+ result.created.push(file);
11042
+ result.staged.push(file);
11043
+ result.modified.push(file);
11044
+ }),
11045
+ parser3("D", " ", (result, file) => {
11046
+ result.deleted.push(file);
11047
+ result.staged.push(file);
11048
+ }),
11049
+ parser3("M", " ", (result, file) => {
11050
+ result.modified.push(file);
11051
+ result.staged.push(file);
11052
+ }),
11053
+ parser3("M", "M", (result, file) => {
11054
+ result.modified.push(file);
11055
+ result.staged.push(file);
11056
+ }),
11050
11057
  parser3("R", " ", (result, file) => {
11051
- append(result.renamed, renamedFile(file));
11058
+ result.renamed.push(renamedFile(file));
11052
11059
  }),
11053
11060
  parser3("R", "M", (result, file) => {
11054
11061
  const renamed = renamedFile(file);
11055
- append(result.renamed, renamed);
11056
- append(result.modified, renamed.to);
11062
+ result.renamed.push(renamed);
11063
+ result.modified.push(renamed.to);
11057
11064
  }),
11058
11065
  parser3("!", "!", (_result, _file) => {
11059
- append(_result.ignored = _result.ignored || [], _file);
11066
+ (_result.ignored = _result.ignored || []).push(_file);
11060
11067
  }),
11061
11068
  parser3(
11062
11069
  "?",
11063
11070
  "?",
11064
- (result, file) => append(result.not_added, file)
11071
+ (result, file) => result.not_added.push(file)
11065
11072
  ),
11066
11073
  ...conflicts(
11067
11074
  "A",
@@ -11154,6 +11161,24 @@ var init_esm4 = __esm({
11154
11161
  ];
11155
11162
  }
11156
11163
  });
11164
+ init_clone = __esm2({
11165
+ "src/lib/tasks/clone.ts"() {
11166
+ "use strict";
11167
+ init_task();
11168
+ init_utils();
11169
+ init_pathspec();
11170
+ cloneTask = (repo, directory, customArgs) => {
11171
+ const commands = ["clone", ...customArgs];
11172
+ filterString(repo) && commands.push(pathspec(repo));
11173
+ filterString(directory) && commands.push(pathspec(directory));
11174
+ return straightThroughStringTask(commands);
11175
+ };
11176
+ cloneMirrorTask = (repo, directory, customArgs) => {
11177
+ append(customArgs, "--mirror");
11178
+ return cloneTask(repo, directory, customArgs);
11179
+ };
11180
+ }
11181
+ });
11157
11182
  simple_git_api_exports = {};
11158
11183
  __export2(simple_git_api_exports, {
11159
11184
  SimpleGitApi: () => SimpleGitApi
@@ -11179,6 +11204,7 @@ var init_esm4 = __esm({
11179
11204
  init_task();
11180
11205
  init_version();
11181
11206
  init_utils();
11207
+ init_clone();
11182
11208
  SimpleGitApi = class {
11183
11209
  constructor(_executor) {
11184
11210
  this._executor = _executor;
@@ -11281,6 +11307,7 @@ var init_esm4 = __esm({
11281
11307
  Object.assign(
11282
11308
  SimpleGitApi.prototype,
11283
11309
  checkout_default(),
11310
+ clone_default(),
11284
11311
  commit_default(),
11285
11312
  config_default(),
11286
11313
  count_objects_default(),
@@ -11484,18 +11511,6 @@ var init_esm4 = __esm({
11484
11511
  init_CheckIgnore();
11485
11512
  }
11486
11513
  });
11487
- clone_exports = {};
11488
- __export2(clone_exports, {
11489
- cloneMirrorTask: () => cloneMirrorTask,
11490
- cloneTask: () => cloneTask
11491
- });
11492
- init_clone = __esm2({
11493
- "src/lib/tasks/clone.ts"() {
11494
- "use strict";
11495
- init_task();
11496
- init_utils();
11497
- }
11498
- });
11499
11514
  init_parse_fetch = __esm2({
11500
11515
  "src/lib/parsers/parse-fetch.ts"() {
11501
11516
  "use strict";
@@ -11677,7 +11692,7 @@ var init_esm4 = __esm({
11677
11692
  var { GitExecutor: GitExecutor2 } = (init_git_executor(), __toCommonJS(git_executor_exports));
11678
11693
  var { SimpleGitApi: SimpleGitApi2 } = (init_simple_git_api(), __toCommonJS(simple_git_api_exports));
11679
11694
  var { Scheduler: Scheduler2 } = (init_scheduler(), __toCommonJS(scheduler_exports));
11680
- var { configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS(task_exports));
11695
+ var { adhocExecTask: adhocExecTask2, configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS(task_exports));
11681
11696
  var {
11682
11697
  asArray: asArray2,
11683
11698
  filterArray: filterArray2,
@@ -11698,7 +11713,6 @@ var init_esm4 = __esm({
11698
11713
  } = (init_branch(), __toCommonJS(branch_exports));
11699
11714
  var { checkIgnoreTask: checkIgnoreTask2 } = (init_check_ignore(), __toCommonJS(check_ignore_exports));
11700
11715
  var { checkIsRepoTask: checkIsRepoTask2 } = (init_check_is_repo(), __toCommonJS(check_is_repo_exports));
11701
- var { cloneTask: cloneTask2, cloneMirrorTask: cloneMirrorTask2 } = (init_clone(), __toCommonJS(clone_exports));
11702
11716
  var { cleanWithOptionsTask: cleanWithOptionsTask2, isCleanOptionsArray: isCleanOptionsArray2 } = (init_clean(), __toCommonJS(clean_exports));
11703
11717
  var { diffSummaryTask: diffSummaryTask2 } = (init_diff(), __toCommonJS(diff_exports));
11704
11718
  var { fetchTask: fetchTask2 } = (init_fetch(), __toCommonJS(fetch_exports));
@@ -11753,24 +11767,6 @@ var init_esm4 = __esm({
11753
11767
  trailingFunctionArgument2(arguments)
11754
11768
  );
11755
11769
  };
11756
- function createCloneTask(api, task, repoPath, localPath) {
11757
- if (typeof repoPath !== "string") {
11758
- return configurationErrorTask2(`git.${api}() requires a string 'repoPath'`);
11759
- }
11760
- return task(repoPath, filterType2(localPath, filterString2), getTrailingOptions2(arguments));
11761
- }
11762
- Git2.prototype.clone = function() {
11763
- return this._runTask(
11764
- createCloneTask("clone", cloneTask2, ...arguments),
11765
- trailingFunctionArgument2(arguments)
11766
- );
11767
- };
11768
- Git2.prototype.mirror = function() {
11769
- return this._runTask(
11770
- createCloneTask("mirror", cloneMirrorTask2, ...arguments),
11771
- trailingFunctionArgument2(arguments)
11772
- );
11773
- };
11774
11770
  Git2.prototype.mv = function(from, to) {
11775
11771
  return this._runTask(moveTask2(from, to), trailingFunctionArgument2(arguments));
11776
11772
  };
@@ -11803,10 +11799,13 @@ var init_esm4 = __esm({
11803
11799
  );
11804
11800
  };
11805
11801
  Git2.prototype.silent = function(silence) {
11806
- console.warn(
11807
- "simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this will be an error in version 3"
11802
+ return this._runTask(
11803
+ adhocExecTask2(
11804
+ () => console.warn(
11805
+ "simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this method will be removed."
11806
+ )
11807
+ )
11808
11808
  );
11809
- return this;
11810
11809
  };
11811
11810
  Git2.prototype.tags = function(options, then) {
11812
11811
  return this._runTask(
@@ -12032,7 +12031,13 @@ var init_esm4 = __esm({
12032
12031
  return this._runTask(task);
12033
12032
  };
12034
12033
  Git2.prototype.clearQueue = function() {
12035
- return this;
12034
+ return this._runTask(
12035
+ adhocExecTask2(
12036
+ () => console.warn(
12037
+ "simple-git deprecation notice: clearQueue() is deprecated and will be removed, switch to using the abortPlugin instead."
12038
+ )
12039
+ )
12040
+ );
12036
12041
  };
12037
12042
  Git2.prototype.checkIgnore = function(pathnames, then) {
12038
12043
  return this._runTask(
@@ -12075,6 +12080,17 @@ var init_esm4 = __esm({
12075
12080
  init_diff_name_status();
12076
12081
  init_grep();
12077
12082
  init_reset();
12083
+ preventUnsafeConfig = [
12084
+ preventConfigBuilder(
12085
+ /^\s*protocol(.[a-z]+)?.allow/i,
12086
+ "allowUnsafeProtocolOverride",
12087
+ "protocol.allow"
12088
+ ),
12089
+ preventConfigBuilder("core.sshCommand", "allowUnsafeSshCommand"),
12090
+ preventConfigBuilder("core.gitProxy", "allowUnsafeGitProxy"),
12091
+ preventConfigBuilder("core.hooksPath", "allowUnsafeHooksPath"),
12092
+ preventConfigBuilder("diff.external", "allowUnsafeDiffExternal")
12093
+ ];
12078
12094
  init_utils();
12079
12095
  init_utils();
12080
12096
  never = (0, import_promise_deferred2.deferred)().promise;
@@ -21688,6 +21704,21 @@ CLI Version: ${options.cliVersion}`;
21688
21704
  }
21689
21705
  });
21690
21706
 
21707
+ // ../commons/core-utils/lib/extractErrorMessage.js
21708
+ function extractErrorMessage(e) {
21709
+ if (typeof e === "string") {
21710
+ return e.length > 0 ? e : "Unknown error";
21711
+ }
21712
+ if (e instanceof Error) {
21713
+ return e.message.length > 0 ? e.message : "Unknown error";
21714
+ }
21715
+ if (typeof e === "object" && e !== null && "message" in e && typeof e["message"] === "string") {
21716
+ return e["message"].length > 0 ? e["message"] : "Unknown error";
21717
+ }
21718
+ const stringified = String(e);
21719
+ return stringified.length > 0 ? stringified : "Unknown error";
21720
+ }
21721
+
21691
21722
  // ../commons/path-utils/lib/convertToOsPath.js
21692
21723
  function convertToOsPath(path5) {
21693
21724
  return path5.replace(/\\/g, "/");
@@ -23638,7 +23669,7 @@ function parseRepository(githubRepository) {
23638
23669
  } else if (parts.length === 3 && parts[0] != null && parts[1] != null && parts[2] != null) {
23639
23670
  [remote, owner, repo] = parts;
23640
23671
  } else {
23641
- throw new Error(`Failed to parse GitHub repostiory ${githubRepository}`);
23672
+ throw new Error(`Failed to parse GitHub repository ${githubRepository}`);
23642
23673
  }
23643
23674
  return newRepositoryReference({ remote, owner, repo });
23644
23675
  }
@@ -23719,7 +23750,7 @@ async function cloneRepository({ githubRepository, installationToken, targetDire
23719
23750
  await git.clone(cloneUrl, ".");
23720
23751
  } catch (error) {
23721
23752
  const elapsed = Date.now() - startTime;
23722
- const errorMessage = error instanceof Error ? error.message : String(error);
23753
+ const errorMessage = extractErrorMessage(error);
23723
23754
  if (errorMessage.includes("ENOENT") || errorMessage.includes("spawn git")) {
23724
23755
  const diagnostics = getGitDiagnostics();
23725
23756
  throw new Error(`Failed to clone repository: git command not found. Self-hosted GitHub mode requires git to be installed on the host machine where the Fern CLI runs. URL: ${sanitizedUrl}. Elapsed: ${elapsed}ms. Debug info: ${diagnostics}. Original error: ${errorMessage}`);
@@ -30687,7 +30718,7 @@ var ReadmeGenerator = class {
30687
30718
  await writer.writeLine();
30688
30719
  await writer.writeLine("```groovy");
30689
30720
  await writer.writeLine("dependencies {");
30690
- await writer.writeLine(` implementation '${maven.group}:${maven.artifact}'`);
30721
+ await writer.writeLine(` implementation '${maven.group}:${maven.artifact}:${maven.version}'`);
30691
30722
  await writer.writeLine("}");
30692
30723
  await writer.writeLine("```");
30693
30724
  await writer.writeLine();
@@ -31334,7 +31365,7 @@ async function findExistingUpdatablePR(octokit, owner, repo, baseBranch, logger)
31334
31365
  }
31335
31366
  return void 0;
31336
31367
  } catch (error) {
31337
- logger.debug(`Error finding existing PRs: ${error instanceof Error ? error.message : String(error)}`);
31368
+ logger.debug(`Error finding existing PRs: ${extractErrorMessage(error)}`);
31338
31369
  return void 0;
31339
31370
  }
31340
31371
  }
@@ -31361,16 +31392,22 @@ async function checkPRHasOnlyGenerationCommits(octokit, owner, repo, pullNumber,
31361
31392
  }
31362
31393
  return true;
31363
31394
  } catch (error) {
31364
- logger.debug(`Error checking PR commits: ${error instanceof Error ? error.message : String(error)}`);
31395
+ logger.debug(`Error checking PR commits: ${extractErrorMessage(error)}`);
31365
31396
  return false;
31366
31397
  }
31367
31398
  }
31368
31399
 
31369
31400
  // src/pipeline/github/parseCommitMessage.ts
31370
- function parseCommitMessageForPR(commitMessage) {
31401
+ function parseCommitMessageForPR(commitMessage, changelogEntry, prDescription, versionBumpReason) {
31371
31402
  const lines = commitMessage.split("\n");
31372
31403
  const prTitle = lines[0]?.trim() || "SDK Generation";
31373
- const prBody = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
31404
+ const bodyFromCommit = lines.slice(1).join("\n").trim() || "Automated SDK generation by Fern";
31405
+ let prBody = prDescription?.trim() || changelogEntry?.trim() || bodyFromCommit;
31406
+ if (versionBumpReason?.trim()) {
31407
+ prBody = `**Version Bump:** ${versionBumpReason.trim()}
31408
+
31409
+ ${prBody}`;
31410
+ }
31374
31411
  return { prTitle, prBody };
31375
31412
  }
31376
31413
 
@@ -31594,14 +31631,17 @@ var GithubStep = class extends BaseStep {
31594
31631
  this.logger.debug(`Pushed ${tagName} tag for generation tracking`);
31595
31632
  result.generationBaseTagSha = generationBaseSha;
31596
31633
  } catch (error) {
31597
- this.logger.debug(
31598
- `Could not push generation tag: ${error instanceof Error ? error.message : String(error)}`
31599
- );
31634
+ this.logger.debug(`Could not push generation tag: ${extractErrorMessage(error)}`);
31600
31635
  }
31601
31636
  }
31602
31637
  }
31603
31638
  const finalCommitMessage = this.config.commitMessage ?? "SDK Generation";
31604
- const { prTitle, prBody } = parseCommitMessageForPR(finalCommitMessage);
31639
+ const { prTitle, prBody } = parseCommitMessageForPR(
31640
+ finalCommitMessage,
31641
+ this.config.changelogEntry,
31642
+ this.config.prDescription,
31643
+ this.config.versionBumpReason
31644
+ );
31605
31645
  const replaySection = formatReplayPrBody(replayResult, { branchName: prBranch, repoUri: this.config.uri });
31606
31646
  const enrichedBody = replaySection != null ? prBody + "\n\n---\n\n" + replaySection : prBody;
31607
31647
  if (isUpdatingExistingPR && existingPR != null) {
@@ -31618,9 +31658,7 @@ var GithubStep = class extends BaseStep {
31618
31658
  });
31619
31659
  this.logger.debug(`Updated PR #${existingPR.number} title and body`);
31620
31660
  } catch (error) {
31621
- this.logger.debug(
31622
- `Failed to update PR title/body: ${error instanceof Error ? error.message : String(error)}`
31623
- );
31661
+ this.logger.debug(`Failed to update PR title/body: ${extractErrorMessage(error)}`);
31624
31662
  }
31625
31663
  } else {
31626
31664
  const head = `${owner}:${prBranch}`;
@@ -31637,7 +31675,7 @@ var GithubStep = class extends BaseStep {
31637
31675
  result.prUrl = pullRequest.html_url;
31638
31676
  result.prNumber = pullRequest.number;
31639
31677
  } catch (error) {
31640
- const message = error instanceof Error ? error.message : String(error);
31678
+ const message = extractErrorMessage(error);
31641
31679
  if (message.includes("A pull request already exists for")) {
31642
31680
  this.logger.warn(`A pull request already exists for ${head}`);
31643
31681
  } else {
@@ -32003,7 +32041,7 @@ var PostGenerationPipeline = class {
32003
32041
  } catch (error) {
32004
32042
  result.success = false;
32005
32043
  result.errors = result.errors ?? [];
32006
- const errorMessage = error instanceof Error ? error.message : String(error);
32044
+ const errorMessage = extractErrorMessage(error);
32007
32045
  result.errors.push(`${step.name} step error: ${errorMessage}`);
32008
32046
  }
32009
32047
  }
@@ -32383,7 +32421,7 @@ void yargs_default(hideBin(process.argv)).scriptName(process.env.CLI_NAME ?? "ge
32383
32421
  try {
32384
32422
  config = JSON.parse(configContent);
32385
32423
  } catch (parseError) {
32386
- const parseMessage = parseError instanceof Error ? parseError.message : String(parseError);
32424
+ const parseMessage = extractErrorMessage(parseError);
32387
32425
  throw new Error(`Failed to parse pipeline config as JSON: ${parseMessage}`);
32388
32426
  }
32389
32427
  config.outputDir = resolve(wd, argv["output-dir"]);
@@ -32417,7 +32455,7 @@ ${result.errors.map((e) => ` - ${e}`).join("\n")}
32417
32455
  process.stdout.write(JSON.stringify(result) + "\n");
32418
32456
  process.exitCode = result.success ? 0 : 1;
32419
32457
  } catch (error) {
32420
- const errorMessage = error instanceof Error ? error.message : String(error);
32458
+ const errorMessage = extractErrorMessage(error);
32421
32459
  process.stderr.write(`Pipeline failed: ${errorMessage}
32422
32460
  `);
32423
32461
  process.exitCode = 1;
@@ -32496,7 +32534,7 @@ ${result.errors.map((e) => ` - ${e}`).join("\n")}
32496
32534
  process.stdout.write(JSON.stringify(result, null, 2) + "\n");
32497
32535
  process.exit(0);
32498
32536
  } catch (error) {
32499
- const errorMessage = error instanceof Error ? error.message : String(error);
32537
+ const errorMessage = extractErrorMessage(error);
32500
32538
  process.stderr.write(`Replay init failed: ${errorMessage}
32501
32539
  `);
32502
32540
  process.exit(1);
@@ -32578,7 +32616,7 @@ Bootstrap complete! Lockfile saved to ${outputDir}/.fern/replay.lock
32578
32616
  }
32579
32617
  process.exit(0);
32580
32618
  } catch (error) {
32581
- const errorMessage = error instanceof Error ? error.message : String(error);
32619
+ const errorMessage = extractErrorMessage(error);
32582
32620
  process.stderr.write(`Bootstrap failed: ${errorMessage}
32583
32621
  `);
32584
32622
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fern-api/generator-cli",
3
- "version": "0.6.11",
3
+ "version": "0.6.14",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fern-api/fern.git",