@better-update/cli 0.29.1 → 0.29.2
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 +65 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -34,7 +34,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
34
34
|
|
|
35
35
|
//#endregion
|
|
36
36
|
//#region package.json
|
|
37
|
-
var version = "0.29.
|
|
37
|
+
var version = "0.29.2";
|
|
38
38
|
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/lib/interactive-mode.ts
|
|
@@ -19130,6 +19130,43 @@ const openFromDownload = (args) => {
|
|
|
19130
19130
|
//#region src/lib/android-keystore.ts
|
|
19131
19131
|
const DEFAULT_KEYSTORE_VALIDITY_DAYS = 1e4;
|
|
19132
19132
|
const renderDistinguishedName = (params) => `CN=${params.commonName}, O=${params.organization}`;
|
|
19133
|
+
const FINGERPRINT_PATTERNS = {
|
|
19134
|
+
md5: /MD5:\s*(?<value>[0-9A-F:]+)/iu,
|
|
19135
|
+
sha1: /SHA-?1:\s*(?<value>[0-9A-F:]+)/iu,
|
|
19136
|
+
sha256: /SHA-?256:\s*(?<value>[0-9A-F:]+)/iu
|
|
19137
|
+
};
|
|
19138
|
+
/**
|
|
19139
|
+
* Parse certificate fingerprints out of `keytool -list -v` output. The fingerprint
|
|
19140
|
+
* labels (`MD5:`, `SHA1:`, `SHA256:`) are stable across keytool locales — only the
|
|
19141
|
+
* surrounding prose is translated — so label-anchored regexes are robust. MD5 is
|
|
19142
|
+
* absent on modern JDKs (dropped from `-v` output); that field stays `undefined`.
|
|
19143
|
+
* keytool already emits the canonical uppercase, colon-separated form the dashboard
|
|
19144
|
+
* displays verbatim, so no normalization is needed.
|
|
19145
|
+
*/
|
|
19146
|
+
const parseKeystoreFingerprints = (output) => ({
|
|
19147
|
+
md5: output.match(FINGERPRINT_PATTERNS.md5)?.groups?.["value"],
|
|
19148
|
+
sha1: output.match(FINGERPRINT_PATTERNS.sha1)?.groups?.["value"],
|
|
19149
|
+
sha256: output.match(FINGERPRINT_PATTERNS.sha256)?.groups?.["value"]
|
|
19150
|
+
});
|
|
19151
|
+
/**
|
|
19152
|
+
* Run `keytool -list -v` against an on-disk keystore and extract its certificate
|
|
19153
|
+
* fingerprints. Only the store password is required to read a certificate. Used at
|
|
19154
|
+
* upload/generate time to populate the public, server-visible fingerprint metadata
|
|
19155
|
+
* the dashboard renders.
|
|
19156
|
+
*/
|
|
19157
|
+
const extractKeystoreFingerprints = (params) => Command.string(Command.make("keytool", "-list", "-v", "-keystore", params.keystorePath, "-alias", params.keyAlias, "-storepass", params.storePassword).pipe(Command.env({ LC_ALL: "C" }))).pipe(Effect.mapError((cause) => new BuildFailedError({
|
|
19158
|
+
step: "extract keystore fingerprints",
|
|
19159
|
+
exitCode: 1,
|
|
19160
|
+
message: `keytool -list failed to run (is the JDK installed?): ${String(cause)}`
|
|
19161
|
+
})), Effect.flatMap((output) => {
|
|
19162
|
+
const fingerprints = parseKeystoreFingerprints(output);
|
|
19163
|
+
if (fingerprints.sha1 === void 0 && fingerprints.sha256 === void 0) return Effect.fail(new BuildFailedError({
|
|
19164
|
+
step: "extract keystore fingerprints",
|
|
19165
|
+
exitCode: 1,
|
|
19166
|
+
message: "keytool produced no SHA-1/SHA-256 fingerprints — verify the key alias and keystore password"
|
|
19167
|
+
}));
|
|
19168
|
+
return Effect.succeed(fingerprints);
|
|
19169
|
+
}));
|
|
19133
19170
|
const generateAndroidKeystore = (input) => Command.exitCode(Command.make("keytool", "-genkeypair", "-v", "-storetype", "JKS", "-keystore", input.outputPath, "-alias", input.keyAlias, "-keyalg", "RSA", "-keysize", "2048", "-validity", String(input.validityDays ?? DEFAULT_KEYSTORE_VALIDITY_DAYS), "-storepass", input.storePassword, "-keypass", input.keyPassword, "-dname", renderDistinguishedName({
|
|
19134
19171
|
commonName: input.commonName,
|
|
19135
19172
|
organization: input.organization
|
|
@@ -19611,8 +19648,18 @@ const generateAndUploadKeystore = (api, input) => Effect.scoped(Effect.gen(funct
|
|
|
19611
19648
|
...compact({ validityDays: input.validityDays })
|
|
19612
19649
|
});
|
|
19613
19650
|
const bytes = yield* fs.readFile(keystorePath);
|
|
19651
|
+
const fingerprints = yield* extractKeystoreFingerprints({
|
|
19652
|
+
keystorePath,
|
|
19653
|
+
keyAlias: input.keyAlias,
|
|
19654
|
+
storePassword: input.storePassword
|
|
19655
|
+
});
|
|
19614
19656
|
const session = yield* openVaultSessionInteractive(api);
|
|
19615
|
-
const metadata = {
|
|
19657
|
+
const metadata = compact({
|
|
19658
|
+
keyAlias: input.keyAlias,
|
|
19659
|
+
md5Fingerprint: fingerprints.md5,
|
|
19660
|
+
sha1Fingerprint: fingerprints.sha1,
|
|
19661
|
+
sha256Fingerprint: fingerprints.sha256
|
|
19662
|
+
});
|
|
19616
19663
|
const envelope = yield* sealForUpload({
|
|
19617
19664
|
session,
|
|
19618
19665
|
credentialType: "keystore",
|
|
@@ -25904,8 +25951,9 @@ const detectFormat = (bytes) => {
|
|
|
25904
25951
|
/**
|
|
25905
25952
|
* Validate keystore bytes + alias/passwords locally before sealing. Mirrors the
|
|
25906
25953
|
* old server check: magic-byte format detection + required-field validation.
|
|
25907
|
-
* Fingerprints
|
|
25908
|
-
*
|
|
25954
|
+
* Fingerprints cannot be derived from the raw bytes; they are extracted separately
|
|
25955
|
+
* via keytool (`extractKeystoreFingerprints` in ./android-keystore) at upload/generate
|
|
25956
|
+
* time and attached to the public metadata.
|
|
25909
25957
|
*/
|
|
25910
25958
|
const validateAndroidKeystore = (params) => Effect.gen(function* () {
|
|
25911
25959
|
if (params.bytes.byteLength < 16) return yield* new CredentialValidationError({ message: "Keystore file too small" });
|
|
@@ -26135,12 +26183,23 @@ const uploadAndroidKeystore = (api, input, bytes) => Effect.gen(function* () {
|
|
|
26135
26183
|
if (input.password === void 0) return yield* missing("password");
|
|
26136
26184
|
if (!input.keyAlias) return yield* missing("key-alias");
|
|
26137
26185
|
if (!input.keyPassword) return yield* missing("key-password");
|
|
26138
|
-
const
|
|
26186
|
+
const parsed = yield* validateAndroidKeystore({
|
|
26139
26187
|
bytes,
|
|
26140
26188
|
keyAlias: input.keyAlias,
|
|
26141
26189
|
keystorePassword: input.password,
|
|
26142
26190
|
keyPassword: input.keyPassword
|
|
26143
|
-
})
|
|
26191
|
+
});
|
|
26192
|
+
const fingerprints = yield* extractKeystoreFingerprints({
|
|
26193
|
+
keystorePath: input.filePath,
|
|
26194
|
+
keyAlias: parsed.keyAlias,
|
|
26195
|
+
storePassword: input.password
|
|
26196
|
+
});
|
|
26197
|
+
const metadata = compact({
|
|
26198
|
+
keyAlias: parsed.keyAlias,
|
|
26199
|
+
md5Fingerprint: fingerprints.md5,
|
|
26200
|
+
sha1Fingerprint: fingerprints.sha1,
|
|
26201
|
+
sha256Fingerprint: fingerprints.sha256
|
|
26202
|
+
});
|
|
26144
26203
|
const envelope = yield* sealForUpload({
|
|
26145
26204
|
session: yield* openVaultSessionInteractive(api),
|
|
26146
26205
|
credentialType: "keystore",
|