@better-update/cli 0.41.2 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +98 -40
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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.
|
|
38
|
+
var version = "0.42.1";
|
|
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))),
|
|
@@ -21978,6 +21981,7 @@ const generateAndUploadKeystore = (api, input) => Effect.scoped(Effect.gen(funct
|
|
|
21978
21981
|
});
|
|
21979
21982
|
const session = yield* openVaultSessionInteractive(api);
|
|
21980
21983
|
const metadata = compact({
|
|
21984
|
+
name: input.name,
|
|
21981
21985
|
keyAlias: input.keyAlias,
|
|
21982
21986
|
md5Fingerprint: fingerprints.md5,
|
|
21983
21987
|
sha1Fingerprint: fingerprints.sha1,
|
|
@@ -22954,15 +22958,17 @@ const makeAppleTeamLabeler = (teams) => {
|
|
|
22954
22958
|
return (internalTeamId) => byId.get(internalTeamId) ?? internalTeamId;
|
|
22955
22959
|
};
|
|
22956
22960
|
/**
|
|
22957
|
-
*
|
|
22958
|
-
*
|
|
22959
|
-
* the
|
|
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.
|
|
22960
22965
|
*/
|
|
22961
22966
|
const keystoreChoice = (item) => {
|
|
22962
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;
|
|
22963
22969
|
return {
|
|
22964
22970
|
value: item.id,
|
|
22965
|
-
label: `${
|
|
22971
|
+
label: `${title} (${details.join(", ")})`,
|
|
22966
22972
|
hint: item.sha1Fingerprint ? `SHA-1 ${item.sha1Fingerprint}` : `id ${item.id.slice(0, 8)}…`
|
|
22967
22973
|
};
|
|
22968
22974
|
};
|
|
@@ -24527,6 +24533,7 @@ const resolveIosStrategy = (profile, projectType) => {
|
|
|
24527
24533
|
|
|
24528
24534
|
//#endregion
|
|
24529
24535
|
//#region src/lib/gradle-config.ts
|
|
24536
|
+
const isValidAndroidPackageName = Schema.is(AndroidPackageName);
|
|
24530
24537
|
/**
|
|
24531
24538
|
* Parse Groovy `build.gradle` to extract key Android config values.
|
|
24532
24539
|
* Returns `undefined` if:
|
|
@@ -24573,12 +24580,27 @@ const parseVersionCode = (raw) => {
|
|
|
24573
24580
|
const extractGradleConfig = (parsed) => {
|
|
24574
24581
|
const defaultConfig = asRecord(asRecord(parsed["android"])?.["defaultConfig"]);
|
|
24575
24582
|
return compact({
|
|
24576
|
-
applicationId:
|
|
24583
|
+
applicationId: extractApplicationId(defaultConfig?.["applicationId"]),
|
|
24577
24584
|
versionCode: parseVersionCode(defaultConfig?.["versionCode"]),
|
|
24578
24585
|
versionName: typeof defaultConfig?.["versionName"] === "string" ? unquote(defaultConfig["versionName"]) : void 0
|
|
24579
24586
|
});
|
|
24580
24587
|
};
|
|
24581
24588
|
const unquote = (input) => input.startsWith("\"") && input.endsWith("\"") ? input.slice(1, -1) : input;
|
|
24589
|
+
/**
|
|
24590
|
+
* Extract a usable Android `applicationId` from the parsed Gradle value.
|
|
24591
|
+
*
|
|
24592
|
+
* react-native-config and similar setups make the id dynamic and env-driven
|
|
24593
|
+
* (e.g. `applicationId project.env.get("APP_ID")`, or a `def` variable). The
|
|
24594
|
+
* Groovy parser surfaces the raw expression text (`project.env.get("APP_ID")`,
|
|
24595
|
+
* `appId`, …), which is not a real package name. Treat anything that isn't a
|
|
24596
|
+
* valid reverse-domain package as unresolved so callers fall back to the
|
|
24597
|
+
* Expo/eas config value instead of building with — or validating — junk.
|
|
24598
|
+
*/
|
|
24599
|
+
const extractApplicationId = (raw) => {
|
|
24600
|
+
if (typeof raw !== "string") return;
|
|
24601
|
+
const value = unquote(raw);
|
|
24602
|
+
return isValidAndroidPackageName(value) ? value : void 0;
|
|
24603
|
+
};
|
|
24582
24604
|
|
|
24583
24605
|
//#endregion
|
|
24584
24606
|
//#region src/application/platform-build.ts
|
|
@@ -26854,6 +26876,13 @@ const uploadIosPushCertificate = (api, input, bytes) => Effect.gen(function* ()
|
|
|
26854
26876
|
|
|
26855
26877
|
//#endregion
|
|
26856
26878
|
//#region src/lib/credentials-manager.ts
|
|
26879
|
+
/** Build a list row, defaulting the optional columns most credential types lack. */
|
|
26880
|
+
const makeRow = (fields) => ({
|
|
26881
|
+
name: null,
|
|
26882
|
+
distribution: null,
|
|
26883
|
+
sha1Fingerprint: null,
|
|
26884
|
+
...fields
|
|
26885
|
+
});
|
|
26857
26886
|
const formatDistribution = (value) => value.toLowerCase().replaceAll("_", "-");
|
|
26858
26887
|
const listAllCredentials = (api) => Effect.gen(function* () {
|
|
26859
26888
|
const [certs, pushKeys, pushCerts, payCerts, passCerts, ascKeys, profiles, keystores, googleKeys] = yield* Effect.all([
|
|
@@ -26868,68 +26897,72 @@ const listAllCredentials = (api) => Effect.gen(function* () {
|
|
|
26868
26897
|
api.googleServiceAccountKeys.list()
|
|
26869
26898
|
], { concurrency: "unbounded" });
|
|
26870
26899
|
return [
|
|
26871
|
-
...certs.items.map((cert) => ({
|
|
26900
|
+
...certs.items.map((cert) => makeRow({
|
|
26872
26901
|
id: cert.id,
|
|
26873
|
-
|
|
26902
|
+
identifier: cert.serialNumber,
|
|
26874
26903
|
platform: "ios",
|
|
26875
26904
|
type: "distribution-certificate",
|
|
26876
|
-
|
|
26905
|
+
createdAt: cert.createdAt
|
|
26877
26906
|
})),
|
|
26878
|
-
...pushKeys.items.map((key) => ({
|
|
26907
|
+
...pushKeys.items.map((key) => makeRow({
|
|
26879
26908
|
id: key.id,
|
|
26880
|
-
|
|
26909
|
+
identifier: key.keyId,
|
|
26881
26910
|
platform: "ios",
|
|
26882
26911
|
type: "push-key",
|
|
26883
|
-
|
|
26912
|
+
createdAt: key.createdAt
|
|
26884
26913
|
})),
|
|
26885
|
-
...pushCerts.items.map((cert) => ({
|
|
26914
|
+
...pushCerts.items.map((cert) => makeRow({
|
|
26886
26915
|
id: cert.id,
|
|
26887
|
-
|
|
26916
|
+
identifier: cert.bundleIdentifier,
|
|
26888
26917
|
platform: "ios",
|
|
26889
26918
|
type: "push-certificate",
|
|
26890
|
-
|
|
26919
|
+
createdAt: cert.createdAt
|
|
26891
26920
|
})),
|
|
26892
|
-
...payCerts.items.map((cert) => ({
|
|
26921
|
+
...payCerts.items.map((cert) => makeRow({
|
|
26893
26922
|
id: cert.id,
|
|
26894
|
-
|
|
26923
|
+
identifier: cert.merchantIdentifier,
|
|
26895
26924
|
platform: "ios",
|
|
26896
26925
|
type: "apple-pay-certificate",
|
|
26897
|
-
|
|
26926
|
+
createdAt: cert.createdAt
|
|
26898
26927
|
})),
|
|
26899
|
-
...passCerts.items.map((cert) => ({
|
|
26928
|
+
...passCerts.items.map((cert) => makeRow({
|
|
26900
26929
|
id: cert.id,
|
|
26901
|
-
|
|
26930
|
+
identifier: cert.passTypeIdentifier,
|
|
26902
26931
|
platform: "ios",
|
|
26903
26932
|
type: "pass-type-certificate",
|
|
26904
|
-
|
|
26933
|
+
createdAt: cert.createdAt
|
|
26905
26934
|
})),
|
|
26906
|
-
...ascKeys.items.map((key) => ({
|
|
26935
|
+
...ascKeys.items.map((key) => makeRow({
|
|
26907
26936
|
id: key.id,
|
|
26908
26937
|
name: key.name,
|
|
26938
|
+
identifier: key.keyId,
|
|
26909
26939
|
platform: "ios",
|
|
26910
26940
|
type: "asc-api-key",
|
|
26911
|
-
|
|
26941
|
+
createdAt: key.createdAt
|
|
26912
26942
|
})),
|
|
26913
|
-
...profiles.items.map((profile) => ({
|
|
26943
|
+
...profiles.items.map((profile) => makeRow({
|
|
26914
26944
|
id: profile.id,
|
|
26915
|
-
|
|
26945
|
+
identifier: profile.profileName ?? profile.bundleIdentifier,
|
|
26916
26946
|
platform: "ios",
|
|
26917
26947
|
type: "provisioning-profile",
|
|
26918
|
-
distribution: formatDistribution(profile.distributionType)
|
|
26948
|
+
distribution: formatDistribution(profile.distributionType),
|
|
26949
|
+
createdAt: profile.createdAt
|
|
26919
26950
|
})),
|
|
26920
|
-
...keystores.items.map((ks) => ({
|
|
26951
|
+
...keystores.items.map((ks) => makeRow({
|
|
26921
26952
|
id: ks.id,
|
|
26922
|
-
name: ks.
|
|
26953
|
+
name: ks.name,
|
|
26954
|
+
identifier: ks.keyAlias,
|
|
26923
26955
|
platform: "android",
|
|
26924
26956
|
type: "keystore",
|
|
26925
|
-
|
|
26957
|
+
sha1Fingerprint: ks.sha1Fingerprint,
|
|
26958
|
+
createdAt: ks.createdAt
|
|
26926
26959
|
})),
|
|
26927
|
-
...googleKeys.items.map((key) => ({
|
|
26960
|
+
...googleKeys.items.map((key) => makeRow({
|
|
26928
26961
|
id: key.id,
|
|
26929
|
-
|
|
26962
|
+
identifier: key.clientEmail,
|
|
26930
26963
|
platform: "android",
|
|
26931
26964
|
type: "google-service-account-key",
|
|
26932
|
-
|
|
26965
|
+
createdAt: key.createdAt
|
|
26933
26966
|
}))
|
|
26934
26967
|
];
|
|
26935
26968
|
});
|
|
@@ -27046,6 +27079,7 @@ const uploadAndroidKeystore = (api, input, bytes) => Effect.gen(function* () {
|
|
|
27046
27079
|
storePassword: input.password
|
|
27047
27080
|
});
|
|
27048
27081
|
const metadata = compact({
|
|
27082
|
+
name: input.name,
|
|
27049
27083
|
keyAlias: parsed.keyAlias,
|
|
27050
27084
|
md5Fingerprint: fingerprints.md5,
|
|
27051
27085
|
sha1Fingerprint: fingerprints.sha1,
|
|
@@ -27224,7 +27258,7 @@ const TYPE_LABELS = {
|
|
|
27224
27258
|
keystore: "Android keystore",
|
|
27225
27259
|
"google-service-account-key": "Google service account key"
|
|
27226
27260
|
};
|
|
27227
|
-
const formatRowLabel$1 = (row) => `${row.name} (${row.id.slice(0, 8)}…)`;
|
|
27261
|
+
const formatRowLabel$1 = (row) => `${row.name ?? row.identifier} (${row.id.slice(0, 8)}…)`;
|
|
27228
27262
|
const pickAndDelete = (ctx, type, humanLabel) => Effect.gen(function* () {
|
|
27229
27263
|
const matches = filterCredentials(yield* listAllCredentials(ctx.api), { type });
|
|
27230
27264
|
if (matches.length === 0) return yield* Console.log(`No ${humanLabel} entries found.`);
|
|
@@ -27389,6 +27423,7 @@ const setupAndroidProjectCredentials = (ctx) => Effect.gen(function* () {
|
|
|
27389
27423
|
});
|
|
27390
27424
|
const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
|
|
27391
27425
|
const alias = yield* promptText("Key alias", { placeholder: "upload-key" });
|
|
27426
|
+
const name = yield* promptText("Display name (label shown in lists)", { placeholder: alias });
|
|
27392
27427
|
const storePassword = yield* promptPassword("Keystore password");
|
|
27393
27428
|
const keyPassword = yield* promptPassword("Key password");
|
|
27394
27429
|
const commonName = yield* promptText("Common name (CN)", { placeholder: "Your App" });
|
|
@@ -27396,6 +27431,7 @@ const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
|
|
|
27396
27431
|
yield* Console.log("Generating keystore with keytool...");
|
|
27397
27432
|
const created = yield* generateAndUploadKeystore(ctx.api, {
|
|
27398
27433
|
keyAlias: alias,
|
|
27434
|
+
name: name.trim().length > 0 ? name : alias,
|
|
27399
27435
|
storePassword,
|
|
27400
27436
|
keyPassword,
|
|
27401
27437
|
commonName,
|
|
@@ -27407,12 +27443,13 @@ const generateAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
|
|
|
27407
27443
|
const uploadAndroidKeystoreInteractive = (ctx) => Effect.gen(function* () {
|
|
27408
27444
|
const filePath = yield* promptText("Path to the keystore (.jks/.keystore) file");
|
|
27409
27445
|
const keyAlias = yield* promptText("Key alias");
|
|
27446
|
+
const name = yield* promptText("Display name (label shown in lists)", { placeholder: keyAlias });
|
|
27410
27447
|
const storePassword = yield* promptPassword("Keystore password");
|
|
27411
27448
|
const keyPassword = yield* promptPassword("Key password");
|
|
27412
27449
|
const created = yield* uploadCredential(ctx.api, {
|
|
27413
27450
|
platform: "android",
|
|
27414
27451
|
type: "keystore",
|
|
27415
|
-
name: keyAlias,
|
|
27452
|
+
name: name.trim().length > 0 ? name : keyAlias,
|
|
27416
27453
|
filePath,
|
|
27417
27454
|
keyAlias,
|
|
27418
27455
|
keyPassword,
|
|
@@ -29448,13 +29485,17 @@ const resolveKeystoreInput = (args) => Effect.gen(function* () {
|
|
|
29448
29485
|
const commonName = args["common-name"] !== void 0 && args["common-name"].trim().length > 0 ? args["common-name"] : yield* promptText("Common name (CN)", { placeholder: "Your App" });
|
|
29449
29486
|
const organization = args.organization !== void 0 && args.organization.trim().length > 0 ? args.organization : yield* promptText("Organization (O)", { placeholder: "Your Company" });
|
|
29450
29487
|
const validityDays = yield* parseValidityDays(args["validity-days"]);
|
|
29488
|
+
const name = args.name !== void 0 && args.name.trim().length > 0 ? args.name : void 0;
|
|
29451
29489
|
return {
|
|
29452
29490
|
alias: yield* ensureNonEmpty(alias, "alias"),
|
|
29453
29491
|
storePassword: yield* ensureNonEmpty(storePassword, "store-password"),
|
|
29454
29492
|
keyPassword: yield* ensureNonEmpty(keyPassword, "key-password"),
|
|
29455
29493
|
commonName: yield* ensureNonEmpty(commonName, "common-name"),
|
|
29456
29494
|
organization: yield* ensureNonEmpty(organization, "organization"),
|
|
29457
|
-
...compact({
|
|
29495
|
+
...compact({
|
|
29496
|
+
validityDays,
|
|
29497
|
+
name
|
|
29498
|
+
})
|
|
29458
29499
|
};
|
|
29459
29500
|
});
|
|
29460
29501
|
const keystoreCommand = defineCommand({
|
|
@@ -29463,6 +29504,10 @@ const keystoreCommand = defineCommand({
|
|
|
29463
29504
|
description: "Generate a new Android upload keystore via keytool and store it server-side"
|
|
29464
29505
|
},
|
|
29465
29506
|
args: {
|
|
29507
|
+
name: {
|
|
29508
|
+
type: "string",
|
|
29509
|
+
description: "Display name (label shown in `credentials list`)"
|
|
29510
|
+
},
|
|
29466
29511
|
alias: {
|
|
29467
29512
|
type: "string",
|
|
29468
29513
|
description: "Key alias"
|
|
@@ -29498,7 +29543,10 @@ const keystoreCommand = defineCommand({
|
|
|
29498
29543
|
keyPassword: resolved.keyPassword,
|
|
29499
29544
|
commonName: resolved.commonName,
|
|
29500
29545
|
organization: resolved.organization,
|
|
29501
|
-
...compact({
|
|
29546
|
+
...compact({
|
|
29547
|
+
validityDays: resolved.validityDays,
|
|
29548
|
+
name: resolved.name
|
|
29549
|
+
})
|
|
29502
29550
|
});
|
|
29503
29551
|
yield* printHuman("");
|
|
29504
29552
|
yield* printHuman("Keystore generated and uploaded.");
|
|
@@ -29893,15 +29941,19 @@ const listCommand$4 = defineCommand({
|
|
|
29893
29941
|
yield* printList([
|
|
29894
29942
|
"ID",
|
|
29895
29943
|
"Name",
|
|
29944
|
+
"Identifier",
|
|
29896
29945
|
"Platform",
|
|
29897
29946
|
"Type",
|
|
29898
|
-
"
|
|
29947
|
+
"Created",
|
|
29948
|
+
"SHA-1"
|
|
29899
29949
|
], filterCredentials(yield* listAllCredentials(yield* apiClient), args.platform ? { platform: args.platform } : {}).map((row) => [
|
|
29900
29950
|
row.id,
|
|
29901
|
-
row.name,
|
|
29951
|
+
row.name ?? "-",
|
|
29952
|
+
row.identifier,
|
|
29902
29953
|
row.platform,
|
|
29903
29954
|
row.type,
|
|
29904
|
-
row.
|
|
29955
|
+
isoDate(row.createdAt),
|
|
29956
|
+
row.sha1Fingerprint ?? "-"
|
|
29905
29957
|
]), "No credentials found.");
|
|
29906
29958
|
}))
|
|
29907
29959
|
});
|
|
@@ -30012,8 +30064,9 @@ const CREDENTIAL_TYPES$2 = [
|
|
|
30012
30064
|
const isPlatform = (value) => value === "ios" || value === "android";
|
|
30013
30065
|
const isType = (value) => CREDENTIAL_TYPES$2.includes(value);
|
|
30014
30066
|
const formatRowLabel = (row) => {
|
|
30067
|
+
const label = row.name ? `${row.name} (${row.identifier})` : row.identifier;
|
|
30015
30068
|
const distro = row.distribution ? ` (${row.distribution})` : "";
|
|
30016
|
-
return `${row.type}: ${
|
|
30069
|
+
return `${row.type}: ${label}${distro} — ${row.id.slice(0, 8)}…`;
|
|
30017
30070
|
};
|
|
30018
30071
|
const removeCommand = defineCommand({
|
|
30019
30072
|
meta: {
|
|
@@ -31183,7 +31236,12 @@ const viewKeystore = (api, id) => Effect.gen(function* () {
|
|
|
31183
31236
|
pairs: [
|
|
31184
31237
|
["ID", item.id],
|
|
31185
31238
|
["Type", "Android upload keystore"],
|
|
31239
|
+
["Name", item.name ?? "-"],
|
|
31186
31240
|
["Key alias", item.keyAlias],
|
|
31241
|
+
["Keystore type", item.keystoreType ?? "-"],
|
|
31242
|
+
["SHA-1", item.sha1Fingerprint ?? "-"],
|
|
31243
|
+
["SHA-256", item.sha256Fingerprint ?? "-"],
|
|
31244
|
+
["MD5", item.md5Fingerprint ?? "-"],
|
|
31187
31245
|
["Created", item.createdAt],
|
|
31188
31246
|
["Updated", item.updatedAt]
|
|
31189
31247
|
],
|