@better-update/cli 0.47.3 → 0.47.4

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/index.mjs CHANGED
@@ -35,7 +35,7 @@ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
35
35
 
36
36
  //#endregion
37
37
  //#region package.json
38
- var version = "0.47.3";
38
+ var version = "0.47.4";
39
39
 
40
40
  //#endregion
41
41
  //#region src/lib/interactive-mode.ts
@@ -21280,6 +21280,66 @@ const commitEdit = (params) => callJsonRaw({
21280
21280
  label: "edits.commit"
21281
21281
  });
21282
21282
 
21283
+ //#endregion
21284
+ //#region src/lib/altool.ts
21285
+ /**
21286
+ * Thin wrapper around `xcrun altool` for App Store delivery: run it without
21287
+ * throwing (failures come back as an {@link ExecResult} with a non-zero exit), and
21288
+ * extract the real failure reason from altool's `--output-format xml` output.
21289
+ */
21290
+ const execFileAsync = promisify(execFile);
21291
+ const ExecErrorSchema = Schema.Struct({
21292
+ code: Schema.optional(Schema.Number),
21293
+ stdout: Schema.optional(Schema.String),
21294
+ stderr: Schema.optional(Schema.String)
21295
+ });
21296
+ const runAltool = (args, extraEnv) => Effect.tryPromise({
21297
+ try: async () => {
21298
+ const options = extraEnv ? {
21299
+ encoding: "utf8",
21300
+ env: {
21301
+ ...process.env,
21302
+ ...extraEnv
21303
+ }
21304
+ } : { encoding: "utf8" };
21305
+ const { stdout, stderr } = await execFileAsync("xcrun", ["altool", ...args], options);
21306
+ return {
21307
+ exitCode: 0,
21308
+ stdout,
21309
+ stderr
21310
+ };
21311
+ },
21312
+ catch: (error) => {
21313
+ const parsed = Schema.decodeUnknownSync(ExecErrorSchema, { onExcessProperty: "ignore" })(typeof error === "object" && error !== null ? error : {});
21314
+ const stdout = parsed.stdout ?? "";
21315
+ const stderr = parsed.stderr ?? String(error);
21316
+ return {
21317
+ exitCode: parsed.code ?? 1,
21318
+ stdout,
21319
+ stderr: stderr === "" ? String(error) : stderr
21320
+ };
21321
+ }
21322
+ }).pipe(Effect.catchAll((result) => Effect.succeed(result)));
21323
+ const unescapeXml = (value) => value.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"").replaceAll("&apos;", "'").replaceAll("&amp;", "&");
21324
+ /**
21325
+ * altool with `--output-format xml` writes the real failure detail to a stdout
21326
+ * plist (`product-errors`), leaving stderr with only a generic
21327
+ * "UPLOAD FAILED … ExitFailure (N)" banner. Pull the human-readable messages so
21328
+ * the surfaced error names the actual cause (asset validation, export compliance,
21329
+ * a duplicate build number, a missing app record…).
21330
+ */
21331
+ const extractAltoolErrors = (xml) => [...xml.matchAll(/<key>message<\/key>\s*<string>(?<message>[\s\S]*?)<\/string>/gu)].flatMap((match) => {
21332
+ const message = match.groups?.["message"];
21333
+ return message === void 0 ? [] : [unescapeXml(message).trim()];
21334
+ });
21335
+ /** Best human-readable altool failure detail: parsed product-errors, else raw streams. */
21336
+ const altoolFailureDetail = (result) => {
21337
+ const messages = extractAltoolErrors(result.stdout);
21338
+ if (messages.length > 0) return messages.join("; ");
21339
+ const combined = `${result.stdout}\n${result.stderr}`.trim();
21340
+ return combined.length > 0 ? combined : "no output";
21341
+ };
21342
+
21283
21343
  //#endregion
21284
21344
  //#region src/lib/apple-asc-connect.ts
21285
21345
  /**
@@ -21537,39 +21597,6 @@ const applyTestFlightConfig = (inputs) => Effect.gen(function* () {
21537
21597
 
21538
21598
  //#endregion
21539
21599
  //#region src/application/submit-flow.ts
21540
- const execFileAsync = promisify(execFile);
21541
- const ExecErrorSchema = Schema.Struct({
21542
- code: Schema.optional(Schema.Number),
21543
- stdout: Schema.optional(Schema.String),
21544
- stderr: Schema.optional(Schema.String)
21545
- });
21546
- const runAltool = (args, extraEnv) => Effect.tryPromise({
21547
- try: async () => {
21548
- const options = extraEnv ? {
21549
- encoding: "utf8",
21550
- env: {
21551
- ...process.env,
21552
- ...extraEnv
21553
- }
21554
- } : { encoding: "utf8" };
21555
- const { stdout, stderr } = await execFileAsync("xcrun", ["altool", ...args], options);
21556
- return {
21557
- exitCode: 0,
21558
- stdout,
21559
- stderr
21560
- };
21561
- },
21562
- catch: (error) => {
21563
- const parsed = Schema.decodeUnknownSync(ExecErrorSchema, { onExcessProperty: "ignore" })(typeof error === "object" && error !== null ? error : {});
21564
- const stdout = parsed.stdout ?? "";
21565
- const stderr = parsed.stderr ?? String(error);
21566
- return {
21567
- exitCode: parsed.code ?? 1,
21568
- stdout,
21569
- stderr: stderr === "" ? String(error) : stderr
21570
- };
21571
- }
21572
- }).pipe(Effect.catchAll((result) => Effect.succeed(result)));
21573
21600
  var CliSubmitError = class extends Schema.TaggedError()("CliSubmitError", {
21574
21601
  code: Schema.String,
21575
21602
  message: Schema.String
@@ -21779,7 +21806,7 @@ const runIosSubmit = (inputs) => Effect.gen(function* () {
21779
21806
  yield* patchSubmissionStatus(inputs.api, inputs.submissionId, {
21780
21807
  status: "ERRORED",
21781
21808
  errorCode: "SUBMISSION_SERVICE_IOS_ALTOOL_FAILED",
21782
- errorMessage: `xcrun altool exited ${String(result.exitCode)}: ${result.stderr}`
21809
+ errorMessage: `xcrun altool exited ${String(result.exitCode)}: ${altoolFailureDetail(result)}`
21783
21810
  });
21784
21811
  return { status: "ERRORED" };
21785
21812
  }