@better-update/cli 0.41.1 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -31,11 +31,11 @@ import { getFormattedSerialNumber, getX509Certificate, parsePKCS12 } from "@expo
31
31
  import qrcode from "qrcode-terminal";
32
32
 
33
33
  //#region \0rolldown/runtime.js
34
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
34
+ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
35
35
 
36
36
  //#endregion
37
37
  //#region package.json
38
- var version = "0.41.1";
38
+ var version = "0.42.0";
39
39
 
40
40
  //#endregion
41
41
  //#region src/lib/interactive-mode.ts
@@ -489,6 +489,8 @@ const RotateVaultBody = Schema.Struct({
489
489
  var AndroidUploadKeystore = class extends Schema.Class("AndroidUploadKeystore")({
490
490
  id: Id,
491
491
  organizationId: Id,
492
+ /** User-supplied label from `credentials upload --name`; null for keystores uploaded before names were stored or generated via keytool. */
493
+ name: Schema.NullOr(Schema.String),
492
494
  keyAlias: Schema.String,
493
495
  md5Fingerprint: Schema.NullOr(Schema.String),
494
496
  sha1Fingerprint: Schema.NullOr(Schema.String),
@@ -505,6 +507,7 @@ var AndroidUploadKeystore = class extends Schema.Class("AndroidUploadKeystore")(
505
507
  const UploadAndroidUploadKeystoreBody = Schema.Struct({
506
508
  id: Id,
507
509
  ...encryptedEnvelopeFields,
510
+ name: Schema.optional(Schema.String.pipe(Schema.maxLength(200))),
508
511
  keyAlias: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(200)),
509
512
  md5Fingerprint: Schema.optional(Schema.String.pipe(Schema.maxLength(200))),
510
513
  sha1Fingerprint: Schema.optional(Schema.String.pipe(Schema.maxLength(200))),
@@ -2404,10 +2407,27 @@ var Project = class extends Schema.Class("Project")({
2404
2407
  lastActivityAt: DateTimeString,
2405
2408
  /** ISO-8601 timestamp the project was archived (read-only); `null` when active. */
2406
2409
  archivedAt: Schema.NullOr(DateTimeString),
2410
+ /** Absolute public CDN URL of the project logo; `null` when none is set. */
2411
+ logoUrl: Schema.NullOr(Schema.String),
2407
2412
  branchCount: Schema.Number,
2408
2413
  channelCount: Schema.Number,
2409
2414
  updateCount: Schema.Number
2410
2415
  }) {};
2416
+ /** Image MIME types accepted for a project logo. */
2417
+ const ProjectLogoContentType = Schema.Literal("image/png", "image/jpeg", "image/webp", "image/svg+xml");
2418
+ /**
2419
+ * Request a presigned PUT to upload a project logo. The server builds the R2 key
2420
+ * itself (`logos/{projectId}`) — never trusting a client-sent key — and signs the
2421
+ * content type into the URL, so the direct upload must send the returned headers.
2422
+ */
2423
+ const ProjectLogoUploadBody = Schema.Struct({ contentType: ProjectLogoContentType });
2424
+ const ProjectLogoUploadResult = Schema.Struct({
2425
+ /** R2 object key the presigned URL targets (`logos/{projectId}`). */
2426
+ key: Schema.String,
2427
+ uploadUrl: Schema.String,
2428
+ uploadExpiresAt: DateTimeString,
2429
+ uploadHeaders: UploadHeaders
2430
+ });
2411
2431
  const ProjectSortColumn = Schema.Literal("lastActivityAt", "name", "createdAt", "branchCount", "channelCount", "updateCount");
2412
2432
  const ProjectSort = sortParam(ProjectSortColumn);
2413
2433
  const ListProjectsParams = Schema.Struct({
@@ -2441,6 +2461,15 @@ var ProjectsGroup = class extends HttpApiGroup.make("projects").add(HttpApiEndpo
2441
2461
  }))).add(HttpApiEndpoint.patch("rename")`/api/projects/${idParam}`.setPayload(UpdateProjectBody).addSuccess(Project).annotateContext(OpenApi.annotations({
2442
2462
  title: "Rename project",
2443
2463
  description: "Rename a project"
2464
+ }))).add(HttpApiEndpoint.post("createLogoUploadUrl")`/api/projects/${idParam}/logo/upload-url`.setPayload(ProjectLogoUploadBody).addSuccess(ProjectLogoUploadResult).annotateContext(OpenApi.annotations({
2465
+ title: "Create project logo upload URL",
2466
+ description: "Request a presigned PUT URL to upload a project logo directly to object storage. Send the returned headers with the upload, then call “Set project logo” to finalize."
2467
+ }))).add(HttpApiEndpoint.put("setLogo")`/api/projects/${idParam}/logo`.addSuccess(Project).annotateContext(OpenApi.annotations({
2468
+ title: "Set project logo",
2469
+ description: "Finalize a project logo after its bytes were uploaded via the presigned URL: validates the stored object and records its public CDN URL on the project."
2470
+ }))).add(HttpApiEndpoint.del("removeLogo")`/api/projects/${idParam}/logo`.addSuccess(Project).annotateContext(OpenApi.annotations({
2471
+ title: "Remove project logo",
2472
+ description: "Remove the project logo, clearing it back to the default avatar"
2444
2473
  }))).add(HttpApiEndpoint.del("delete")`/api/projects/${idParam}`.addSuccess(DeleteProjectResult).annotateContext(OpenApi.annotations({
2445
2474
  title: "Delete project",
2446
2475
  description: "Delete a project and all its branches, channels, and updates"
@@ -2450,7 +2479,7 @@ var ProjectsGroup = class extends HttpApiGroup.make("projects").add(HttpApiEndpo
2450
2479
  }))).add(HttpApiEndpoint.post("unarchive")`/api/projects/${idParam}/unarchive`.addSuccess(Project).annotateContext(OpenApi.annotations({
2451
2480
  title: "Unarchive project",
2452
2481
  description: "Restore an archived project to active, writable state"
2453
- }))).addError(NotFound).addError(Conflict).addError(Forbidden).annotateContext(OpenApi.annotations({
2482
+ }))).addError(NotFound).addError(Conflict).addError(BadRequest).addError(Forbidden).annotateContext(OpenApi.annotations({
2454
2483
  title: "Projects",
2455
2484
  description: "Project management endpoints"
2456
2485
  })) {};
@@ -4970,7 +4999,7 @@ const CODE_SIGNING_ALG = "rsa-v1_5-sha256";
4970
4999
  * `sig="<base64>", keyid="<id>", alg="rsa-v1_5-sha256"`. `alg` defaults to
4971
5000
  * {@link CODE_SIGNING_ALG} (the only value SDK56 verifies).
4972
5001
  */
4973
- const buildExpoSignatureHeader = (params) => serializeDictionary(new Map([
5002
+ const buildExpoSignatureHeader = (params) => serializeDictionary(/* @__PURE__ */ new Map([
4974
5003
  ["sig", [params.sig, /* @__PURE__ */ new Map()]],
4975
5004
  ["keyid", [params.keyid, /* @__PURE__ */ new Map()]],
4976
5005
  ["alg", [params.alg ?? "rsa-v1_5-sha256", /* @__PURE__ */ new Map()]]
@@ -6791,7 +6820,7 @@ function wrapMacConstructor(keyLen, macCons, fromMsg) {
6791
6820
  const mac = macCons;
6792
6821
  const getArgs = fromMsg || (() => []);
6793
6822
  const macC = (msg, key) => mac(key, ...getArgs(msg)).update(msg).digest();
6794
- const tmp = mac(new Uint8Array(keyLen), ...getArgs(new Uint8Array(0)));
6823
+ const tmp = mac(new Uint8Array(keyLen), ...getArgs(/* @__PURE__ */ new Uint8Array(0)));
6795
6824
  macC.outputLen = tmp.outputLen;
6796
6825
  macC.blockLen = tmp.blockLen;
6797
6826
  macC.create = (key, ...args) => mac(key, ...args);
@@ -6888,7 +6917,7 @@ function u64Lengths(dataLength, aadLength, isLE) {
6888
6917
  anumber$4(dataLength);
6889
6918
  anumber$4(aadLength);
6890
6919
  abool$2(isLE);
6891
- const num = new Uint8Array(16);
6920
+ const num = /* @__PURE__ */ new Uint8Array(16);
6892
6921
  const view = createView$2(num);
6893
6922
  view.setBigUint64(0, BigInt(aadLength), isLE);
6894
6923
  view.setBigUint64(8, BigInt(dataLength), isLE);
@@ -7145,7 +7174,7 @@ function createCipher(core, opts) {
7145
7174
  toClean.push(k = copyBytes$3(key));
7146
7175
  sigma = sigma32_32;
7147
7176
  } else if (l === 16 && allowShortKeys) {
7148
- k = new Uint8Array(32);
7177
+ k = /* @__PURE__ */ new Uint8Array(32);
7149
7178
  k.set(key);
7150
7179
  k.set(key, 16);
7151
7180
  sigma = sigma16_32;
@@ -7171,7 +7200,7 @@ function createCipher(core, opts) {
7171
7200
  const nonceNcLen = 16 - counterLength;
7172
7201
  if (nonceNcLen !== nonce.length) throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);
7173
7202
  if (nonceNcLen !== 12) {
7174
- const nc = new Uint8Array(12);
7203
+ const nc = /* @__PURE__ */ new Uint8Array(12);
7175
7204
  nc.set(nonce, counterRight ? 0 : 12 - nonce.length);
7176
7205
  nonce = nc;
7177
7206
  toClean.push(nonce);
@@ -7229,10 +7258,10 @@ function u8to16(a, i) {
7229
7258
  var Poly1305 = class {
7230
7259
  blockLen = 16;
7231
7260
  outputLen = 16;
7232
- buffer = new Uint8Array(16);
7233
- r = new Uint16Array(10);
7234
- h = new Uint16Array(10);
7235
- pad = new Uint16Array(8);
7261
+ buffer = /* @__PURE__ */ new Uint8Array(16);
7262
+ r = /* @__PURE__ */ new Uint16Array(10);
7263
+ h = /* @__PURE__ */ new Uint16Array(10);
7264
+ pad = /* @__PURE__ */ new Uint16Array(8);
7236
7265
  pos = 0;
7237
7266
  finished = false;
7238
7267
  destroyed = false;
@@ -7368,7 +7397,7 @@ var Poly1305 = class {
7368
7397
  }
7369
7398
  finalize() {
7370
7399
  const { h, pad } = this;
7371
- const g = new Uint16Array(10);
7400
+ const g = /* @__PURE__ */ new Uint16Array(10);
7372
7401
  let c = h[1] >>> 13;
7373
7402
  h[1] &= 8191;
7374
7403
  for (let i = 2; i < 10; i++) {
@@ -9683,7 +9712,7 @@ function blamka(Ah, Al, Bh, Bl) {
9683
9712
  l: Rll | 0
9684
9713
  };
9685
9714
  }
9686
- const A2_BUF = new Uint32Array(256);
9715
+ const A2_BUF = /* @__PURE__ */ new Uint32Array(256);
9687
9716
  function G(a, b, c, d) {
9688
9717
  let Al = A2_BUF[2 * a], Ah = A2_BUF[2 * a + 1];
9689
9718
  let Bl = A2_BUF[2 * b], Bh = A2_BUF[2 * b + 1];
@@ -9750,7 +9779,7 @@ function block(x, xPos, yPos, outPos, needXor) {
9750
9779
  }
9751
9780
  function Hp(A, dkLen) {
9752
9781
  const A8 = u8(A);
9753
- const T = new Uint32Array(1);
9782
+ const T = /* @__PURE__ */ new Uint32Array(1);
9754
9783
  const T8 = u8(T);
9755
9784
  T[0] = swap8IfBE(dkLen);
9756
9785
  if (dkLen <= 64) return blake2b.create({ dkLen }).update(T8).update(A8).digest();
@@ -9811,7 +9840,7 @@ function argon2Init(password, salt, type, opts) {
9811
9840
  key = abytesOrZero(key, "key");
9812
9841
  personalization = abytesOrZero(personalization, "personalization");
9813
9842
  const h = blake2b.create();
9814
- const BUF = new Uint32Array(1);
9843
+ const BUF = /* @__PURE__ */ new Uint32Array(1);
9815
9844
  const BUF8 = u8(BUF);
9816
9845
  for (let item of [
9817
9846
  p,
@@ -9833,7 +9862,7 @@ function argon2Init(password, salt, type, opts) {
9833
9862
  BUF[0] = swap8IfBE(i.length);
9834
9863
  h.update(BUF8).update(i);
9835
9864
  }
9836
- const H0 = new Uint32Array(18);
9865
+ const H0 = /* @__PURE__ */ new Uint32Array(18);
9837
9866
  const H0_8 = u8(H0);
9838
9867
  h.digestInto(H0_8);
9839
9868
  const lanes = p;
@@ -9879,7 +9908,7 @@ function argon2Init(password, salt, type, opts) {
9879
9908
  };
9880
9909
  }
9881
9910
  function argon2Output(B, p, laneLen, dkLen) {
9882
- const B_final = new Uint32Array(256);
9911
+ const B_final = /* @__PURE__ */ new Uint32Array(256);
9883
9912
  for (let l = 0; l < p; l++) for (let j = 0; j < 256; j++) B_final[j] ^= B[256 * (laneLen * l + laneLen - 1) + j];
9884
9913
  const res = Hp(swap32IfBE$1(B_final), dkLen);
9885
9914
  clean$1(B, B_final);
@@ -10689,7 +10718,7 @@ function pbkdf2Output(PRF, PRFSalt, DK, prfW, u) {
10689
10718
  function pbkdf2(hash, password, salt, opts) {
10690
10719
  const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
10691
10720
  let prfW;
10692
- const arr = new Uint8Array(4);
10721
+ const arr = /* @__PURE__ */ new Uint8Array(4);
10693
10722
  const view = createView$1(arr);
10694
10723
  const u = new Uint8Array(PRF.outputLen);
10695
10724
  for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
@@ -13841,7 +13870,7 @@ const rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
13841
13870
  const rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
13842
13871
  /** `keccakf1600` internal function, additionally allows to adjust round count. */
13843
13872
  function keccakP(s, rounds = 24) {
13844
- const B = new Uint32Array(10);
13873
+ const B = /* @__PURE__ */ new Uint32Array(10);
13845
13874
  for (let round = 24 - rounds; round < 24; round++) {
13846
13875
  for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
13847
13876
  for (let x = 0; x < 10; x += 2) {
@@ -13898,7 +13927,7 @@ var Keccak = class Keccak {
13898
13927
  this.rounds = rounds;
13899
13928
  anumber$1(outputLen, "outputLen");
13900
13929
  if (!(0 < blockLen && blockLen < 200)) throw new Error("only keccak-f1600 function is supported");
13901
- this.state = new Uint8Array(200);
13930
+ this.state = /* @__PURE__ */ new Uint8Array(200);
13902
13931
  this.state32 = u32(this.state);
13903
13932
  }
13904
13933
  clone() {
@@ -14454,7 +14483,7 @@ const genKPKE = (opts) => {
14454
14483
  },
14455
14484
  keygen: (seed) => {
14456
14485
  abytes$1(seed, 32, "seed");
14457
- const seedDst = new Uint8Array(33);
14486
+ const seedDst = /* @__PURE__ */ new Uint8Array(33);
14458
14487
  seedDst.set(seed);
14459
14488
  seedDst[32] = K;
14460
14489
  const seedHash = HASH512(seedDst);
@@ -18298,7 +18327,7 @@ function domBuffer(arr) {
18298
18327
  var LineReader = class {
18299
18328
  s;
18300
18329
  transcript = [];
18301
- buf = new Uint8Array(0);
18330
+ buf = /* @__PURE__ */ new Uint8Array(0);
18302
18331
  constructor(stream) {
18303
18332
  this.s = stream.getReader();
18304
18333
  }
@@ -18569,20 +18598,20 @@ const hpkeMLKEM768P256 = 80;
18569
18598
  const hpkeDHKEMP256 = 16;
18570
18599
  function hpkeContext(kemID, sharedSecret, info) {
18571
18600
  const suiteID = hpkeSuiteID(kemID);
18572
- const pskIDHash = hpkeLabeledExtract(suiteID, void 0, "psk_id_hash", new Uint8Array(0));
18601
+ const pskIDHash = hpkeLabeledExtract(suiteID, void 0, "psk_id_hash", /* @__PURE__ */ new Uint8Array(0));
18573
18602
  const infoHash = hpkeLabeledExtract(suiteID, void 0, "info_hash", info);
18574
18603
  const ksContext = new Uint8Array(1 + pskIDHash.length + infoHash.length);
18575
18604
  ksContext[0] = 0;
18576
18605
  ksContext.set(pskIDHash, 1);
18577
18606
  ksContext.set(infoHash, 1 + pskIDHash.length);
18578
- const secret = hpkeLabeledExtract(suiteID, sharedSecret, "secret", new Uint8Array(0));
18607
+ const secret = hpkeLabeledExtract(suiteID, sharedSecret, "secret", /* @__PURE__ */ new Uint8Array(0));
18579
18608
  return {
18580
18609
  key: hpkeLabeledExpand(suiteID, secret, "key", ksContext, 32),
18581
18610
  nonce: hpkeLabeledExpand(suiteID, secret, "base_nonce", ksContext, 12)
18582
18611
  };
18583
18612
  }
18584
18613
  function hpkeSuiteID(kemID) {
18585
- const suiteID = new Uint8Array(10);
18614
+ const suiteID = /* @__PURE__ */ new Uint8Array(10);
18586
18615
  suiteID.set(new TextEncoder().encode("HPKE"), 0);
18587
18616
  suiteID[4] = kemID >> 8 & 255;
18588
18617
  suiteID[5] = kemID & 255;
@@ -18627,7 +18656,7 @@ function hpkeDHKEMP256Encapsulate(recipient) {
18627
18656
  const kemContext = new Uint8Array(encapsulatedKey.length + recipient.length);
18628
18657
  kemContext.set(encapsulatedKey, 0);
18629
18658
  kemContext.set(recipient, encapsulatedKey.length);
18630
- const suiteID = new Uint8Array(5);
18659
+ const suiteID = /* @__PURE__ */ new Uint8Array(5);
18631
18660
  suiteID.set(new TextEncoder().encode("KEM"), 0);
18632
18661
  suiteID[3] = 0;
18633
18662
  suiteID[4] = 16;
@@ -18748,7 +18777,7 @@ var ScryptRecipient = class {
18748
18777
  wrapFileKey(fileKey) {
18749
18778
  const salt = randomBytes$4(16);
18750
18779
  const label = "age-encryption.org/v1/scrypt";
18751
- const labelAndSalt = new Uint8Array(44);
18780
+ const labelAndSalt = /* @__PURE__ */ new Uint8Array(44);
18752
18781
  labelAndSalt.set(new TextEncoder().encode(label));
18753
18782
  labelAndSalt.set(salt, 28);
18754
18783
  const key = scrypt(this.passphrase, labelAndSalt, {
@@ -18780,7 +18809,7 @@ var ScryptIdentity = class {
18780
18809
  const logN = Number(s.args[2]);
18781
18810
  if (logN > 20) throw Error("scrypt work factor is too high");
18782
18811
  const label = "age-encryption.org/v1/scrypt";
18783
- const labelAndSalt = new Uint8Array(44);
18812
+ const labelAndSalt = /* @__PURE__ */ new Uint8Array(44);
18784
18813
  labelAndSalt.set(new TextEncoder().encode(label));
18785
18814
  labelAndSalt.set(salt, 28);
18786
18815
  const key = scrypt(this.passphrase, labelAndSalt, {
@@ -18796,11 +18825,11 @@ var ScryptIdentity = class {
18796
18825
  }
18797
18826
  };
18798
18827
  function encryptFileKey(fileKey, key) {
18799
- return chacha20poly1305(key, new Uint8Array(12)).encrypt(fileKey);
18828
+ return chacha20poly1305(key, /* @__PURE__ */ new Uint8Array(12)).encrypt(fileKey);
18800
18829
  }
18801
18830
  function decryptFileKey(body, key) {
18802
18831
  if (body.length !== 32) throw Error("invalid stanza");
18803
- const nonce = new Uint8Array(12);
18832
+ const nonce = /* @__PURE__ */ new Uint8Array(12);
18804
18833
  try {
18805
18834
  return chacha20poly1305(key, nonce).decrypt(body);
18806
18835
  } catch {
@@ -18817,7 +18846,7 @@ const chacha20poly1305Overhead = 16;
18817
18846
  const chunkSize = /* @__PURE__ */ (() => 64 * 1024)();
18818
18847
  const chunkSizeWithOverhead = /* @__PURE__ */ (() => chunkSize + chacha20poly1305Overhead)();
18819
18848
  function decryptSTREAM(key) {
18820
- const streamNonce = new Uint8Array(12);
18849
+ const streamNonce = /* @__PURE__ */ new Uint8Array(12);
18821
18850
  const incNonce = () => {
18822
18851
  for (let i = streamNonce.length - 2; i >= 0; i--) {
18823
18852
  streamNonce[i]++;
@@ -18863,7 +18892,7 @@ function plaintextSize(ciphertextSize) {
18863
18892
  return size;
18864
18893
  }
18865
18894
  function encryptSTREAM(key) {
18866
- const streamNonce = new Uint8Array(12);
18895
+ const streamNonce = /* @__PURE__ */ new Uint8Array(12);
18867
18896
  const incNonce = () => {
18868
18897
  for (let i = streamNonce.length - 2; i >= 0; i--) {
18869
18898
  streamNonce[i]++;
@@ -21952,6 +21981,7 @@ const generateAndUploadKeystore = (api, input) => Effect.scoped(Effect.gen(funct
21952
21981
  });
21953
21982
  const session = yield* openVaultSessionInteractive(api);
21954
21983
  const metadata = compact({
21984
+ name: input.name,
21955
21985
  keyAlias: input.keyAlias,
21956
21986
  md5Fingerprint: fingerprints.md5,
21957
21987
  sha1Fingerprint: fingerprints.sha1,
@@ -22928,15 +22958,17 @@ const makeAppleTeamLabeler = (teams) => {
22928
22958
  return (internalTeamId) => byId.get(internalTeamId) ?? internalTeamId;
22929
22959
  };
22930
22960
  /**
22931
- * Keystore aliases are often cryptic, so surface the type + creation date in the
22932
- * label and the SHA-1 fingerprint (which matches the Play Console upload key) on
22933
- * the active-row hint.
22961
+ * Aliases collide across white-label apps (many keystores share `jmango`), so
22962
+ * lead with the user-supplied name when present and keep the alias alongside it;
22963
+ * surface the type + creation date in the label and the SHA-1 fingerprint (which
22964
+ * matches the Play Console upload key) on the active-row hint.
22934
22965
  */
22935
22966
  const keystoreChoice = (item) => {
22936
22967
  const details = [item.keystoreType, `created ${isoDate(item.createdAt)}`].filter((part) => part !== null);
22968
+ const title = item.name ? `${item.name} (alias ${item.keyAlias})` : item.keyAlias;
22937
22969
  return {
22938
22970
  value: item.id,
22939
- label: `${item.keyAlias} (${details.join(", ")})`,
22971
+ label: `${title} (${details.join(", ")})`,
22940
22972
  hint: item.sha1Fingerprint ? `SHA-1 ${item.sha1Fingerprint}` : `id ${item.id.slice(0, 8)}…`
22941
22973
  };
22942
22974
  };
@@ -23973,7 +24005,7 @@ const validateEmbeddedProfile = (bundleDir, expectedUuid, expectedTeamId, bundle
23973
24005
  //#endregion
23974
24006
  //#region src/lib/xcode-targets.ts
23975
24007
  /** Product types whose targets require code-signing with a provisioning profile. */
23976
- const SIGNED_PRODUCT_TYPES = new Set([
24008
+ const SIGNED_PRODUCT_TYPES = /* @__PURE__ */ new Set([
23977
24009
  "com.apple.product-type.application",
23978
24010
  "com.apple.product-type.app-extension",
23979
24011
  "com.apple.product-type.messages-extension",
@@ -26828,6 +26860,13 @@ const uploadIosPushCertificate = (api, input, bytes) => Effect.gen(function* ()
26828
26860
 
26829
26861
  //#endregion
26830
26862
  //#region src/lib/credentials-manager.ts
26863
+ /** Build a list row, defaulting the optional columns most credential types lack. */
26864
+ const makeRow = (fields) => ({
26865
+ name: null,
26866
+ distribution: null,
26867
+ sha1Fingerprint: null,
26868
+ ...fields
26869
+ });
26831
26870
  const formatDistribution = (value) => value.toLowerCase().replaceAll("_", "-");
26832
26871
  const listAllCredentials = (api) => Effect.gen(function* () {
26833
26872
  const [certs, pushKeys, pushCerts, payCerts, passCerts, ascKeys, profiles, keystores, googleKeys] = yield* Effect.all([
@@ -26842,68 +26881,72 @@ const listAllCredentials = (api) => Effect.gen(function* () {
26842
26881
  api.googleServiceAccountKeys.list()
26843
26882
  ], { concurrency: "unbounded" });
26844
26883
  return [
26845
- ...certs.items.map((cert) => ({
26884
+ ...certs.items.map((cert) => makeRow({
26846
26885
  id: cert.id,
26847
- name: cert.serialNumber,
26886
+ identifier: cert.serialNumber,
26848
26887
  platform: "ios",
26849
26888
  type: "distribution-certificate",
26850
- distribution: null
26889
+ createdAt: cert.createdAt
26851
26890
  })),
26852
- ...pushKeys.items.map((key) => ({
26891
+ ...pushKeys.items.map((key) => makeRow({
26853
26892
  id: key.id,
26854
- name: key.keyId,
26893
+ identifier: key.keyId,
26855
26894
  platform: "ios",
26856
26895
  type: "push-key",
26857
- distribution: null
26896
+ createdAt: key.createdAt
26858
26897
  })),
26859
- ...pushCerts.items.map((cert) => ({
26898
+ ...pushCerts.items.map((cert) => makeRow({
26860
26899
  id: cert.id,
26861
- name: cert.bundleIdentifier,
26900
+ identifier: cert.bundleIdentifier,
26862
26901
  platform: "ios",
26863
26902
  type: "push-certificate",
26864
- distribution: null
26903
+ createdAt: cert.createdAt
26865
26904
  })),
26866
- ...payCerts.items.map((cert) => ({
26905
+ ...payCerts.items.map((cert) => makeRow({
26867
26906
  id: cert.id,
26868
- name: cert.merchantIdentifier,
26907
+ identifier: cert.merchantIdentifier,
26869
26908
  platform: "ios",
26870
26909
  type: "apple-pay-certificate",
26871
- distribution: null
26910
+ createdAt: cert.createdAt
26872
26911
  })),
26873
- ...passCerts.items.map((cert) => ({
26912
+ ...passCerts.items.map((cert) => makeRow({
26874
26913
  id: cert.id,
26875
- name: cert.passTypeIdentifier,
26914
+ identifier: cert.passTypeIdentifier,
26876
26915
  platform: "ios",
26877
26916
  type: "pass-type-certificate",
26878
- distribution: null
26917
+ createdAt: cert.createdAt
26879
26918
  })),
26880
- ...ascKeys.items.map((key) => ({
26919
+ ...ascKeys.items.map((key) => makeRow({
26881
26920
  id: key.id,
26882
26921
  name: key.name,
26922
+ identifier: key.keyId,
26883
26923
  platform: "ios",
26884
26924
  type: "asc-api-key",
26885
- distribution: null
26925
+ createdAt: key.createdAt
26886
26926
  })),
26887
- ...profiles.items.map((profile) => ({
26927
+ ...profiles.items.map((profile) => makeRow({
26888
26928
  id: profile.id,
26889
- name: profile.profileName ?? profile.bundleIdentifier,
26929
+ identifier: profile.profileName ?? profile.bundleIdentifier,
26890
26930
  platform: "ios",
26891
26931
  type: "provisioning-profile",
26892
- distribution: formatDistribution(profile.distributionType)
26932
+ distribution: formatDistribution(profile.distributionType),
26933
+ createdAt: profile.createdAt
26893
26934
  })),
26894
- ...keystores.items.map((ks) => ({
26935
+ ...keystores.items.map((ks) => makeRow({
26895
26936
  id: ks.id,
26896
- name: ks.keyAlias,
26937
+ name: ks.name,
26938
+ identifier: ks.keyAlias,
26897
26939
  platform: "android",
26898
26940
  type: "keystore",
26899
- distribution: null
26941
+ sha1Fingerprint: ks.sha1Fingerprint,
26942
+ createdAt: ks.createdAt
26900
26943
  })),
26901
- ...googleKeys.items.map((key) => ({
26944
+ ...googleKeys.items.map((key) => makeRow({
26902
26945
  id: key.id,
26903
- name: key.clientEmail,
26946
+ identifier: key.clientEmail,
26904
26947
  platform: "android",
26905
26948
  type: "google-service-account-key",
26906
- distribution: null
26949
+ createdAt: key.createdAt
26907
26950
  }))
26908
26951
  ];
26909
26952
  });
@@ -27020,6 +27063,7 @@ const uploadAndroidKeystore = (api, input, bytes) => Effect.gen(function* () {
27020
27063
  storePassword: input.password
27021
27064
  });
27022
27065
  const metadata = compact({
27066
+ name: input.name,
27023
27067
  keyAlias: parsed.keyAlias,
27024
27068
  md5Fingerprint: fingerprints.md5,
27025
27069
  sha1Fingerprint: fingerprints.sha1,
@@ -27198,7 +27242,7 @@ const TYPE_LABELS = {
27198
27242
  keystore: "Android keystore",
27199
27243
  "google-service-account-key": "Google service account key"
27200
27244
  };
27201
- const formatRowLabel$1 = (row) => `${row.name} (${row.id.slice(0, 8)}…)`;
27245
+ const formatRowLabel$1 = (row) => `${row.name ?? row.identifier} (${row.id.slice(0, 8)}…)`;
27202
27246
  const pickAndDelete = (ctx, type, humanLabel) => Effect.gen(function* () {
27203
27247
  const matches = filterCredentials(yield* listAllCredentials(ctx.api), { type });
27204
27248
  if (matches.length === 0) return yield* Console.log(`No ${humanLabel} entries found.`);
@@ -27363,6 +27407,7 @@ const setupAndroidProjectCredentials = (ctx) => Effect.gen(function* () {
27363
27407
  });
27364
27408
  const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
27365
27409
  const alias = yield* promptText("Key alias", { placeholder: "upload-key" });
27410
+ const name = yield* promptText("Display name (label shown in lists)", { placeholder: alias });
27366
27411
  const storePassword = yield* promptPassword("Keystore password");
27367
27412
  const keyPassword = yield* promptPassword("Key password");
27368
27413
  const commonName = yield* promptText("Common name (CN)", { placeholder: "Your App" });
@@ -27370,6 +27415,7 @@ const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
27370
27415
  yield* Console.log("Generating keystore with keytool...");
27371
27416
  const created = yield* generateAndUploadKeystore(ctx.api, {
27372
27417
  keyAlias: alias,
27418
+ name: name.trim().length > 0 ? name : alias,
27373
27419
  storePassword,
27374
27420
  keyPassword,
27375
27421
  commonName,
@@ -27381,12 +27427,13 @@ const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
27381
27427
  const uploadAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
27382
27428
  const filePath = yield* promptText("Path to the keystore (.jks/.keystore) file");
27383
27429
  const keyAlias = yield* promptText("Key alias");
27430
+ const name = yield* promptText("Display name (label shown in lists)", { placeholder: keyAlias });
27384
27431
  const storePassword = yield* promptPassword("Keystore password");
27385
27432
  const keyPassword = yield* promptPassword("Key password");
27386
27433
  const created = yield* uploadCredential(ctx.api, {
27387
27434
  platform: "android",
27388
27435
  type: "keystore",
27389
- name: keyAlias,
27436
+ name: name.trim().length > 0 ? name : keyAlias,
27390
27437
  filePath,
27391
27438
  keyAlias,
27392
27439
  keyPassword,
@@ -29422,13 +29469,17 @@ const resolveKeystoreInput = (args) => Effect.gen(function* () {
29422
29469
  const commonName = args["common-name"] !== void 0 && args["common-name"].trim().length > 0 ? args["common-name"] : yield* promptText("Common name (CN)", { placeholder: "Your App" });
29423
29470
  const organization = args.organization !== void 0 && args.organization.trim().length > 0 ? args.organization : yield* promptText("Organization (O)", { placeholder: "Your Company" });
29424
29471
  const validityDays = yield* parseValidityDays(args["validity-days"]);
29472
+ const name = args.name !== void 0 && args.name.trim().length > 0 ? args.name : void 0;
29425
29473
  return {
29426
29474
  alias: yield* ensureNonEmpty(alias, "alias"),
29427
29475
  storePassword: yield* ensureNonEmpty(storePassword, "store-password"),
29428
29476
  keyPassword: yield* ensureNonEmpty(keyPassword, "key-password"),
29429
29477
  commonName: yield* ensureNonEmpty(commonName, "common-name"),
29430
29478
  organization: yield* ensureNonEmpty(organization, "organization"),
29431
- ...compact({ validityDays })
29479
+ ...compact({
29480
+ validityDays,
29481
+ name
29482
+ })
29432
29483
  };
29433
29484
  });
29434
29485
  const keystoreCommand = defineCommand({
@@ -29437,6 +29488,10 @@ const keystoreCommand = defineCommand({
29437
29488
  description: "Generate a new Android upload keystore via keytool and store it server-side"
29438
29489
  },
29439
29490
  args: {
29491
+ name: {
29492
+ type: "string",
29493
+ description: "Display name (label shown in `credentials list`)"
29494
+ },
29440
29495
  alias: {
29441
29496
  type: "string",
29442
29497
  description: "Key alias"
@@ -29472,7 +29527,10 @@ const keystoreCommand = defineCommand({
29472
29527
  keyPassword: resolved.keyPassword,
29473
29528
  commonName: resolved.commonName,
29474
29529
  organization: resolved.organization,
29475
- ...compact({ validityDays: resolved.validityDays })
29530
+ ...compact({
29531
+ validityDays: resolved.validityDays,
29532
+ name: resolved.name
29533
+ })
29476
29534
  });
29477
29535
  yield* printHuman("");
29478
29536
  yield* printHuman("Keystore generated and uploaded.");
@@ -29867,15 +29925,19 @@ const listCommand$4 = defineCommand({
29867
29925
  yield* printList([
29868
29926
  "ID",
29869
29927
  "Name",
29928
+ "Identifier",
29870
29929
  "Platform",
29871
29930
  "Type",
29872
- "Distribution"
29931
+ "Created",
29932
+ "SHA-1"
29873
29933
  ], filterCredentials(yield* listAllCredentials(yield* apiClient), args.platform ? { platform: args.platform } : {}).map((row) => [
29874
29934
  row.id,
29875
- row.name,
29935
+ row.name ?? "-",
29936
+ row.identifier,
29876
29937
  row.platform,
29877
29938
  row.type,
29878
- row.distribution ?? "-"
29939
+ isoDate(row.createdAt),
29940
+ row.sha1Fingerprint ?? "-"
29879
29941
  ]), "No credentials found.");
29880
29942
  }))
29881
29943
  });
@@ -29986,8 +30048,9 @@ const CREDENTIAL_TYPES$2 = [
29986
30048
  const isPlatform = (value) => value === "ios" || value === "android";
29987
30049
  const isType = (value) => CREDENTIAL_TYPES$2.includes(value);
29988
30050
  const formatRowLabel = (row) => {
30051
+ const label = row.name ? `${row.name} (${row.identifier})` : row.identifier;
29989
30052
  const distro = row.distribution ? ` (${row.distribution})` : "";
29990
- return `${row.type}: ${row.name}${distro} — ${row.id.slice(0, 8)}…`;
30053
+ return `${row.type}: ${label}${distro} — ${row.id.slice(0, 8)}…`;
29991
30054
  };
29992
30055
  const removeCommand = defineCommand({
29993
30056
  meta: {
@@ -31157,7 +31220,12 @@ const viewKeystore = (api, id) => Effect.gen(function* () {
31157
31220
  pairs: [
31158
31221
  ["ID", item.id],
31159
31222
  ["Type", "Android upload keystore"],
31223
+ ["Name", item.name ?? "-"],
31160
31224
  ["Key alias", item.keyAlias],
31225
+ ["Keystore type", item.keystoreType ?? "-"],
31226
+ ["SHA-1", item.sha1Fingerprint ?? "-"],
31227
+ ["SHA-256", item.sha256Fingerprint ?? "-"],
31228
+ ["MD5", item.md5Fingerprint ?? "-"],
31161
31229
  ["Created", item.createdAt],
31162
31230
  ["Updated", item.updatedAt]
31163
31231
  ],