@better-update/cli 0.17.0 → 0.18.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 +176 -113
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { createServer } from "node:http";
|
|
|
14
14
|
import { maxBy, uniqBy } from "es-toolkit";
|
|
15
15
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
16
16
|
import forge from "node-forge";
|
|
17
|
-
import { createReadStream, existsSync, promises, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { accessSync, chmodSync, constants, createReadStream, existsSync, promises, readFileSync, writeFileSync } from "node:fs";
|
|
18
18
|
import { spawn as spawn$1 } from "node-pty";
|
|
19
19
|
import chalk from "chalk";
|
|
20
20
|
import os from "node:os";
|
|
@@ -31,7 +31,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
31
31
|
|
|
32
32
|
//#endregion
|
|
33
33
|
//#region package.json
|
|
34
|
-
var version = "0.
|
|
34
|
+
var version = "0.18.1";
|
|
35
35
|
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/lib/interactive-mode.ts
|
|
@@ -200,11 +200,11 @@ var NotAcceptable = class extends Schema.TaggedError()("NotAcceptable", { messag
|
|
|
200
200
|
//#endregion
|
|
201
201
|
//#region ../../packages/api/src/groups/android-application-identifiers.ts
|
|
202
202
|
const idParam$16 = HttpApiSchema.param("id", Schema.String);
|
|
203
|
-
const projectIdParam$
|
|
204
|
-
var AndroidApplicationIdentifiersGroup = class extends HttpApiGroup.make("androidApplicationIdentifiers").add(HttpApiEndpoint.get("list")`/api/projects/${projectIdParam$
|
|
203
|
+
const projectIdParam$4 = HttpApiSchema.param("projectId", Schema.String);
|
|
204
|
+
var AndroidApplicationIdentifiersGroup = class extends HttpApiGroup.make("androidApplicationIdentifiers").add(HttpApiEndpoint.get("list")`/api/projects/${projectIdParam$4}/android-application-identifiers`.addSuccess(Schema.Struct({ items: Schema.Array(AndroidApplicationIdentifier) })).annotateContext(OpenApi.annotations({
|
|
205
205
|
title: "List Android application identifiers",
|
|
206
206
|
description: "List all Android package identifiers for a project"
|
|
207
|
-
}))).add(HttpApiEndpoint.post("create")`/api/projects/${projectIdParam$
|
|
207
|
+
}))).add(HttpApiEndpoint.post("create")`/api/projects/${projectIdParam$4}/android-application-identifiers`.setPayload(CreateAndroidApplicationIdentifierBody).addSuccess(AndroidApplicationIdentifier, { status: 201 }).annotateContext(OpenApi.annotations({
|
|
208
208
|
title: "Create Android application identifier",
|
|
209
209
|
description: "Register an Android package name for a project"
|
|
210
210
|
}))).add(HttpApiEndpoint.del("delete")`/api/android-application-identifiers/${idParam$16}`.addSuccess(DeleteAndroidApplicationIdentifierResult).annotateContext(OpenApi.annotations({
|
|
@@ -612,11 +612,11 @@ const AssetUploadResult = Schema.Struct({
|
|
|
612
612
|
|
|
613
613
|
//#endregion
|
|
614
614
|
//#region ../../packages/api/src/groups/assets.ts
|
|
615
|
-
const hashParam = HttpApiSchema.param("hash", Schema.String);
|
|
615
|
+
const hashParam$1 = HttpApiSchema.param("hash", Schema.String);
|
|
616
616
|
var AssetsGroup = class extends HttpApiGroup.make("assets").add(HttpApiEndpoint.post("upload", "/api/assets/upload").setPayload(AssetUploadBody).addSuccess(AssetUploadResult, { status: 201 }).annotateContext(OpenApi.annotations({
|
|
617
617
|
title: "Upload assets",
|
|
618
618
|
description: "Upload asset files to R2 storage (deduplicated by content hash)"
|
|
619
|
-
}))).add(HttpApiEndpoint.post("finalize")`/api/assets/${hashParam}/finalize`.addSuccess(Asset).annotateContext(OpenApi.annotations({
|
|
619
|
+
}))).add(HttpApiEndpoint.post("finalize")`/api/assets/${hashParam$1}/finalize`.addSuccess(Asset).annotateContext(OpenApi.annotations({
|
|
620
620
|
title: "Finalize asset upload",
|
|
621
621
|
description: "Verify a directly uploaded asset in R2 and mark it available for updates"
|
|
622
622
|
}))).addError(BadRequest).addError(NotFound).addError(Forbidden).annotateContext(OpenApi.annotations({
|
|
@@ -721,7 +721,8 @@ const ResolveBuildCredentialsIosBody = Schema.Struct({
|
|
|
721
721
|
});
|
|
722
722
|
const ResolveBuildCredentialsAndroidBody = Schema.Struct({
|
|
723
723
|
platform: Schema.Literal("android"),
|
|
724
|
-
applicationIdentifier: AndroidPackageName
|
|
724
|
+
applicationIdentifier: AndroidPackageName,
|
|
725
|
+
buildProfile: Schema.optional(Schema.String.pipe(Schema.minLength(1), Schema.maxLength(120)))
|
|
725
726
|
});
|
|
726
727
|
const ResolveBuildCredentialsBody = Schema.Union(ResolveBuildCredentialsIosBody, ResolveBuildCredentialsAndroidBody);
|
|
727
728
|
const IosBuildDistributionCertificate = Schema.Struct({
|
|
@@ -777,8 +778,8 @@ const ResolveBuildCredentialsResult = Schema.Union(ResolveBuildCredentialsIosRes
|
|
|
777
778
|
|
|
778
779
|
//#endregion
|
|
779
780
|
//#region ../../packages/api/src/groups/build-credentials.ts
|
|
780
|
-
const projectIdParam$
|
|
781
|
-
var BuildCredentialsGroup = class extends HttpApiGroup.make("buildCredentials").add(HttpApiEndpoint.post("resolve")`/api/projects/${projectIdParam$
|
|
781
|
+
const projectIdParam$3 = HttpApiSchema.param("projectId", Schema.String);
|
|
782
|
+
var BuildCredentialsGroup = class extends HttpApiGroup.make("buildCredentials").add(HttpApiEndpoint.post("resolve")`/api/projects/${projectIdParam$3}/build-credentials/resolve`.setPayload(ResolveBuildCredentialsBody).addSuccess(ResolveBuildCredentialsResult).annotateContext(OpenApi.annotations({
|
|
782
783
|
title: "Resolve build credentials",
|
|
783
784
|
description: "Return decrypted signing assets for a project build. Regenerates the iOS provisioning profile via Apple ASC when the registered device roster has changed since the profile was last generated."
|
|
784
785
|
}))).addError(NotFound).addError(BadRequest).addError(Forbidden).annotateContext(OpenApi.annotations({
|
|
@@ -789,6 +790,7 @@ var BuildCredentialsGroup = class extends HttpApiGroup.make("buildCredentials").
|
|
|
789
790
|
//#endregion
|
|
790
791
|
//#region ../../packages/api/src/domain/build.ts
|
|
791
792
|
const Distribution = Schema.Literal("app-store", "ad-hoc", "development", "enterprise", "simulator", "play-store", "direct");
|
|
793
|
+
const BuildAudience = Schema.Literal("internal", "store");
|
|
792
794
|
const ArtifactFormat = Schema.Literal("ipa", "apk", "aab", "tar.gz");
|
|
793
795
|
const Sha256Hex = Schema.String.pipe(Schema.pattern(/^[a-fA-F0-9]{64}$/u), Schema.maxLength(64));
|
|
794
796
|
const CreateBuildCommonFields = {
|
|
@@ -805,6 +807,7 @@ const CreateBuildCommonFields = {
|
|
|
805
807
|
key: Schema.String,
|
|
806
808
|
value: Schema.Unknown
|
|
807
809
|
})),
|
|
810
|
+
fingerprintHash: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
808
811
|
sha256: Sha256Hex,
|
|
809
812
|
byteSize: Schema.Number.pipe(Schema.nonNegative())
|
|
810
813
|
};
|
|
@@ -822,6 +825,7 @@ var Build = class extends Schema.Class("Build")({
|
|
|
822
825
|
gitCommit: Schema.NullOr(Schema.String),
|
|
823
826
|
message: Schema.NullOr(Schema.String),
|
|
824
827
|
metadataJson: Schema.String,
|
|
828
|
+
fingerprintHash: Schema.NullOr(Schema.String),
|
|
825
829
|
createdAt: DateTimeString
|
|
826
830
|
}) {};
|
|
827
831
|
var BuildArtifact = class extends Schema.Class("BuildArtifact")({
|
|
@@ -873,6 +877,7 @@ const ListBuildsParams = Schema.Struct({
|
|
|
873
877
|
profile: Schema.optional(Schema.String),
|
|
874
878
|
runtimeVersion: Schema.optional(Schema.String),
|
|
875
879
|
distribution: Schema.optional(Distribution),
|
|
880
|
+
audience: Schema.optional(BuildAudience),
|
|
876
881
|
...PaginationParams.fields,
|
|
877
882
|
sort: Schema.optional(BuildSort)
|
|
878
883
|
});
|
|
@@ -1245,6 +1250,108 @@ var EnvVarsGroup = class extends HttpApiGroup.make("env-vars").add(HttpApiEndpoi
|
|
|
1245
1250
|
description: "Manage environment variables for project builds and deployments"
|
|
1246
1251
|
})) {};
|
|
1247
1252
|
|
|
1253
|
+
//#endregion
|
|
1254
|
+
//#region ../../packages/api/src/domain/update.ts
|
|
1255
|
+
var Update = class extends Schema.Class("Update")({
|
|
1256
|
+
id: Id,
|
|
1257
|
+
branchId: Id,
|
|
1258
|
+
runtimeVersion: Schema.String,
|
|
1259
|
+
platform: Platform,
|
|
1260
|
+
message: Schema.String,
|
|
1261
|
+
metadataJson: Schema.String,
|
|
1262
|
+
extraJson: Schema.NullOr(Schema.String),
|
|
1263
|
+
groupId: Schema.String,
|
|
1264
|
+
rolloutPercentage: Schema.Number,
|
|
1265
|
+
isRollback: Schema.Boolean,
|
|
1266
|
+
signature: Schema.NullOr(Schema.String),
|
|
1267
|
+
certificateChain: Schema.NullOr(Schema.String),
|
|
1268
|
+
manifestBody: Schema.NullOr(Schema.String),
|
|
1269
|
+
directiveBody: Schema.NullOr(Schema.String),
|
|
1270
|
+
fingerprintHash: Schema.NullOr(Schema.String),
|
|
1271
|
+
totalAssetSize: Schema.Number,
|
|
1272
|
+
createdAt: DateTimeString
|
|
1273
|
+
}) {};
|
|
1274
|
+
const UpdateSortColumn = Schema.Literal("createdAt", "runtimeVersion", "platform", "rolloutPercentage");
|
|
1275
|
+
/**
|
|
1276
|
+
* Sort param: column name optionally prefixed with `-` for descending.
|
|
1277
|
+
* Example: `runtimeVersion` (asc), `-createdAt` (desc).
|
|
1278
|
+
*/
|
|
1279
|
+
const UpdateSort = Schema.Union(UpdateSortColumn, Schema.TemplateLiteral("-", UpdateSortColumn));
|
|
1280
|
+
const ListUpdatesParams = Schema.Struct({
|
|
1281
|
+
projectId: Id,
|
|
1282
|
+
branchId: Schema.optional(Id),
|
|
1283
|
+
platform: Schema.optional(Platform),
|
|
1284
|
+
runtimeVersion: Schema.optional(Schema.String),
|
|
1285
|
+
...PaginationParams.fields,
|
|
1286
|
+
sort: Schema.optional(UpdateSort)
|
|
1287
|
+
});
|
|
1288
|
+
const AssetRef = Schema.Struct({
|
|
1289
|
+
hash: Schema.String,
|
|
1290
|
+
key: Schema.String,
|
|
1291
|
+
isLaunch: Schema.Boolean,
|
|
1292
|
+
contentChecksum: Schema.optional(Schema.String)
|
|
1293
|
+
});
|
|
1294
|
+
const UpdateAssetEntry = Schema.Struct({
|
|
1295
|
+
hash: Schema.String,
|
|
1296
|
+
key: Schema.String,
|
|
1297
|
+
isLaunch: Schema.Boolean,
|
|
1298
|
+
contentChecksum: Schema.NullOr(Schema.String)
|
|
1299
|
+
});
|
|
1300
|
+
const CreateUpdateBody = Schema.Struct({
|
|
1301
|
+
branch: Schema.String.pipe(Schema.minLength(1)),
|
|
1302
|
+
slug: Schema.String.pipe(Schema.minLength(1)),
|
|
1303
|
+
runtimeVersion: Schema.String.pipe(Schema.minLength(1)),
|
|
1304
|
+
platform: Platform,
|
|
1305
|
+
message: Schema.String,
|
|
1306
|
+
groupId: Schema.String.pipe(Schema.minLength(1)),
|
|
1307
|
+
metadata: Schema.Record({
|
|
1308
|
+
key: Schema.String,
|
|
1309
|
+
value: Schema.Unknown
|
|
1310
|
+
}),
|
|
1311
|
+
extra: Schema.optional(Schema.Record({
|
|
1312
|
+
key: Schema.String,
|
|
1313
|
+
value: Schema.Unknown
|
|
1314
|
+
})),
|
|
1315
|
+
assets: Schema.Array(AssetRef),
|
|
1316
|
+
manifestBody: Schema.optional(Schema.String),
|
|
1317
|
+
directiveBody: Schema.optional(Schema.String),
|
|
1318
|
+
isRollback: Schema.optional(Schema.Boolean),
|
|
1319
|
+
signature: Schema.optional(Schema.String),
|
|
1320
|
+
certificateChain: Schema.optional(Schema.String),
|
|
1321
|
+
rolloutPercentage: Schema.optional(Schema.Number.pipe(Schema.int(), Schema.between(1, 100))),
|
|
1322
|
+
fingerprintHash: Schema.optional(Schema.String.pipe(Schema.minLength(1)))
|
|
1323
|
+
});
|
|
1324
|
+
const RepublishBody = Schema.Struct({
|
|
1325
|
+
sourceUpdateId: Schema.optional(Id),
|
|
1326
|
+
sourceGroupId: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1327
|
+
destinationBranchId: Schema.optional(Id),
|
|
1328
|
+
destinationChannel: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1329
|
+
message: Schema.optional(Schema.String),
|
|
1330
|
+
signedUpdates: Schema.optional(Schema.Array(Schema.Struct({
|
|
1331
|
+
sourceUpdateId: Id,
|
|
1332
|
+
manifestBody: Schema.String.pipe(Schema.minLength(1)),
|
|
1333
|
+
signature: Schema.String.pipe(Schema.minLength(1)),
|
|
1334
|
+
certificateChain: Schema.String.pipe(Schema.minLength(1))
|
|
1335
|
+
})))
|
|
1336
|
+
});
|
|
1337
|
+
const RepublishResult = Schema.Struct({ updates: Schema.Array(Update) });
|
|
1338
|
+
const DeleteUpdateResult = Schema.Struct({ deleted: Schema.Number });
|
|
1339
|
+
|
|
1340
|
+
//#endregion
|
|
1341
|
+
//#region ../../packages/api/src/groups/fingerprints.ts
|
|
1342
|
+
const projectIdParam$2 = HttpApiSchema.param("projectId", Id);
|
|
1343
|
+
const hashParam = HttpApiSchema.param("hash", Schema.String.pipe(Schema.minLength(1)));
|
|
1344
|
+
const FingerprintDetail = Schema.Struct({
|
|
1345
|
+
hash: Schema.String,
|
|
1346
|
+
projectId: Id,
|
|
1347
|
+
builds: Schema.Array(BuildWithArtifact),
|
|
1348
|
+
updates: Schema.Array(Update)
|
|
1349
|
+
});
|
|
1350
|
+
var FingerprintsGroup = class extends HttpApiGroup.make("fingerprints").add(HttpApiEndpoint.get("get")`/api/projects/${projectIdParam$2}/fingerprints/${hashParam}`.addSuccess(FingerprintDetail).annotateContext(OpenApi.annotations({
|
|
1351
|
+
title: "Get fingerprint",
|
|
1352
|
+
description: "Fetch builds and updates compatible with a given fingerprint hash within a project."
|
|
1353
|
+
}))).addError(Forbidden, { status: 403 }).addError(NotFound, { status: 404 }).addError(BadRequest, { status: 400 }) {};
|
|
1354
|
+
|
|
1248
1355
|
//#endregion
|
|
1249
1356
|
//#region ../../packages/api/src/domain/google-service-account-key.ts
|
|
1250
1357
|
var GoogleServiceAccountKey = class extends Schema.Class("GoogleServiceAccountKey")({
|
|
@@ -1433,83 +1540,6 @@ var ProjectsGroup = class extends HttpApiGroup.make("projects").add(HttpApiEndpo
|
|
|
1433
1540
|
description: "Project management endpoints"
|
|
1434
1541
|
})) {};
|
|
1435
1542
|
|
|
1436
|
-
//#endregion
|
|
1437
|
-
//#region ../../packages/api/src/domain/update.ts
|
|
1438
|
-
var Update = class extends Schema.Class("Update")({
|
|
1439
|
-
id: Id,
|
|
1440
|
-
branchId: Id,
|
|
1441
|
-
runtimeVersion: Schema.String,
|
|
1442
|
-
platform: Platform,
|
|
1443
|
-
message: Schema.String,
|
|
1444
|
-
metadataJson: Schema.String,
|
|
1445
|
-
extraJson: Schema.NullOr(Schema.String),
|
|
1446
|
-
groupId: Schema.String,
|
|
1447
|
-
rolloutPercentage: Schema.Number,
|
|
1448
|
-
isRollback: Schema.Boolean,
|
|
1449
|
-
signature: Schema.NullOr(Schema.String),
|
|
1450
|
-
certificateChain: Schema.NullOr(Schema.String),
|
|
1451
|
-
manifestBody: Schema.NullOr(Schema.String),
|
|
1452
|
-
directiveBody: Schema.NullOr(Schema.String),
|
|
1453
|
-
createdAt: DateTimeString
|
|
1454
|
-
}) {};
|
|
1455
|
-
const UpdateSortColumn = Schema.Literal("createdAt", "runtimeVersion", "platform", "rolloutPercentage");
|
|
1456
|
-
/**
|
|
1457
|
-
* Sort param: column name optionally prefixed with `-` for descending.
|
|
1458
|
-
* Example: `runtimeVersion` (asc), `-createdAt` (desc).
|
|
1459
|
-
*/
|
|
1460
|
-
const UpdateSort = Schema.Union(UpdateSortColumn, Schema.TemplateLiteral("-", UpdateSortColumn));
|
|
1461
|
-
const ListUpdatesParams = Schema.Struct({
|
|
1462
|
-
projectId: Id,
|
|
1463
|
-
branchId: Schema.optional(Id),
|
|
1464
|
-
platform: Schema.optional(Platform),
|
|
1465
|
-
...PaginationParams.fields,
|
|
1466
|
-
sort: Schema.optional(UpdateSort)
|
|
1467
|
-
});
|
|
1468
|
-
const AssetRef = Schema.Struct({
|
|
1469
|
-
hash: Schema.String,
|
|
1470
|
-
key: Schema.String,
|
|
1471
|
-
isLaunch: Schema.Boolean,
|
|
1472
|
-
contentChecksum: Schema.optional(Schema.String)
|
|
1473
|
-
});
|
|
1474
|
-
const CreateUpdateBody = Schema.Struct({
|
|
1475
|
-
branch: Schema.String.pipe(Schema.minLength(1)),
|
|
1476
|
-
slug: Schema.String.pipe(Schema.minLength(1)),
|
|
1477
|
-
runtimeVersion: Schema.String.pipe(Schema.minLength(1)),
|
|
1478
|
-
platform: Platform,
|
|
1479
|
-
message: Schema.String,
|
|
1480
|
-
groupId: Schema.String.pipe(Schema.minLength(1)),
|
|
1481
|
-
metadata: Schema.Record({
|
|
1482
|
-
key: Schema.String,
|
|
1483
|
-
value: Schema.Unknown
|
|
1484
|
-
}),
|
|
1485
|
-
extra: Schema.optional(Schema.Record({
|
|
1486
|
-
key: Schema.String,
|
|
1487
|
-
value: Schema.Unknown
|
|
1488
|
-
})),
|
|
1489
|
-
assets: Schema.Array(AssetRef),
|
|
1490
|
-
manifestBody: Schema.optional(Schema.String),
|
|
1491
|
-
directiveBody: Schema.optional(Schema.String),
|
|
1492
|
-
isRollback: Schema.optional(Schema.Boolean),
|
|
1493
|
-
signature: Schema.optional(Schema.String),
|
|
1494
|
-
certificateChain: Schema.optional(Schema.String),
|
|
1495
|
-
rolloutPercentage: Schema.optional(Schema.Number.pipe(Schema.int(), Schema.between(1, 100)))
|
|
1496
|
-
});
|
|
1497
|
-
const RepublishBody = Schema.Struct({
|
|
1498
|
-
sourceUpdateId: Schema.optional(Id),
|
|
1499
|
-
sourceGroupId: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1500
|
-
destinationBranchId: Schema.optional(Id),
|
|
1501
|
-
destinationChannel: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1502
|
-
message: Schema.optional(Schema.String),
|
|
1503
|
-
signedUpdates: Schema.optional(Schema.Array(Schema.Struct({
|
|
1504
|
-
sourceUpdateId: Id,
|
|
1505
|
-
manifestBody: Schema.String.pipe(Schema.minLength(1)),
|
|
1506
|
-
signature: Schema.String.pipe(Schema.minLength(1)),
|
|
1507
|
-
certificateChain: Schema.String.pipe(Schema.minLength(1))
|
|
1508
|
-
})))
|
|
1509
|
-
});
|
|
1510
|
-
const RepublishResult = Schema.Struct({ updates: Schema.Array(Update) });
|
|
1511
|
-
const DeleteUpdateResult = Schema.Struct({ deleted: Schema.Number });
|
|
1512
|
-
|
|
1513
1543
|
//#endregion
|
|
1514
1544
|
//#region ../../packages/api/src/groups/updates.ts
|
|
1515
1545
|
const idParam$1 = HttpApiSchema.param("id", Schema.String);
|
|
@@ -1528,6 +1558,12 @@ var UpdatesGroup = class extends HttpApiGroup.make("updates").add(HttpApiEndpoin
|
|
|
1528
1558
|
}))).add(HttpApiEndpoint.get("get")`/api/updates/${idParam$1}`.addSuccess(Update).annotateContext(OpenApi.annotations({
|
|
1529
1559
|
title: "Get update",
|
|
1530
1560
|
description: "Fetch a single update by ID"
|
|
1561
|
+
}))).add(HttpApiEndpoint.get("getGroup")`/api/update-groups/${groupIdParam}`.addSuccess(Schema.Struct({ items: Schema.Array(Update) })).annotateContext(OpenApi.annotations({
|
|
1562
|
+
title: "Get update group",
|
|
1563
|
+
description: "Fetch all updates in a group (paired iOS + Android variants)"
|
|
1564
|
+
}))).add(HttpApiEndpoint.get("listAssets")`/api/updates/${idParam$1}/assets`.addSuccess(Schema.Array(UpdateAssetEntry)).annotateContext(OpenApi.annotations({
|
|
1565
|
+
title: "List update assets",
|
|
1566
|
+
description: "Fetch the asset references (key + hash + launch flag) for an update"
|
|
1531
1567
|
}))).add(HttpApiEndpoint.del("deleteGroup")`/api/updates/${groupIdParam}`.addSuccess(DeleteUpdateResult).annotateContext(OpenApi.annotations({
|
|
1532
1568
|
title: "Delete update group",
|
|
1533
1569
|
description: "Delete all updates in a group (paired iOS + Android updates)"
|
|
@@ -1605,7 +1641,7 @@ var WebhooksGroup = class extends HttpApiGroup.make("webhooks").add(HttpApiEndpo
|
|
|
1605
1641
|
|
|
1606
1642
|
//#endregion
|
|
1607
1643
|
//#region ../../packages/api/src/api.ts
|
|
1608
|
-
var ManagementApi = class extends HttpApi.make("management-api").add(ProjectsGroup).add(BranchesGroup).add(ChannelsGroup).add(UpdatesGroup).add(AssetsGroup).add(AnalyticsGroup).add(BuildsGroup).add(EnvVarsGroup).add(AuditLogsGroup).add(DevicesGroup).add(AppleTeamsGroup).add(AppleDistributionCertificatesGroup).add(ApplePushKeysGroup).add(AscApiKeysGroup).add(AppleProvisioningProfilesGroup).add(GoogleServiceAccountKeysGroup).add(IosBundleConfigurationsGroup).add(AndroidApplicationIdentifiersGroup).add(AndroidUploadKeystoresGroup).add(AndroidBuildCredentialsGroup).add(BuildCredentialsGroup).add(MeGroup).add(WebhooksGroup).middleware(Authentication).annotateContext(OpenApi.annotations({
|
|
1644
|
+
var ManagementApi = class extends HttpApi.make("management-api").add(ProjectsGroup).add(BranchesGroup).add(ChannelsGroup).add(UpdatesGroup).add(AssetsGroup).add(AnalyticsGroup).add(BuildsGroup).add(EnvVarsGroup).add(FingerprintsGroup).add(AuditLogsGroup).add(DevicesGroup).add(AppleTeamsGroup).add(AppleDistributionCertificatesGroup).add(ApplePushKeysGroup).add(AscApiKeysGroup).add(AppleProvisioningProfilesGroup).add(GoogleServiceAccountKeysGroup).add(IosBundleConfigurationsGroup).add(AndroidApplicationIdentifiersGroup).add(AndroidUploadKeystoresGroup).add(AndroidBuildCredentialsGroup).add(BuildCredentialsGroup).add(MeGroup).add(WebhooksGroup).middleware(Authentication).annotateContext(OpenApi.annotations({
|
|
1609
1645
|
title: "Better Update Management API",
|
|
1610
1646
|
version: "1.0.0",
|
|
1611
1647
|
description: "Management API for OTA update publishing, deployment, and analytics"
|
|
@@ -4150,7 +4186,8 @@ const downloadAndroidCredentials = (api, options) => Effect.gen(function* () {
|
|
|
4150
4186
|
path: { projectId: options.projectId },
|
|
4151
4187
|
payload: {
|
|
4152
4188
|
platform: "android",
|
|
4153
|
-
applicationIdentifier: options.applicationIdentifier
|
|
4189
|
+
applicationIdentifier: options.applicationIdentifier,
|
|
4190
|
+
...options.buildProfile === void 0 ? {} : { buildProfile: options.buildProfile }
|
|
4154
4191
|
}
|
|
4155
4192
|
}).pipe(Effect.mapError((cause) => resolveErrorToMissingCredentials(cause, "android")));
|
|
4156
4193
|
if (resolved.platform !== "android") return yield* Effect.fail(new MissingCredentialsError({
|
|
@@ -4407,7 +4444,23 @@ const mergeEnv$1 = (overrides) => {
|
|
|
4407
4444
|
for (const [key, value] of Object.entries(overrides)) merged[key] = value;
|
|
4408
4445
|
return merged;
|
|
4409
4446
|
};
|
|
4447
|
+
let spawnHelperChecked = false;
|
|
4448
|
+
const ensureSpawnHelperExecutable = () => {
|
|
4449
|
+
if (spawnHelperChecked) return;
|
|
4450
|
+
spawnHelperChecked = true;
|
|
4451
|
+
if (process$1.platform === "win32") return;
|
|
4452
|
+
try {
|
|
4453
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
4454
|
+
const helperPath = path.join(path.dirname(nodeRequire.resolve("node-pty/package.json")), "prebuilds", `${process$1.platform}-${process$1.arch}`, "spawn-helper");
|
|
4455
|
+
try {
|
|
4456
|
+
accessSync(helperPath, constants.X_OK);
|
|
4457
|
+
} catch {
|
|
4458
|
+
chmodSync(helperPath, 493);
|
|
4459
|
+
}
|
|
4460
|
+
} catch {}
|
|
4461
|
+
};
|
|
4410
4462
|
const trySpawn = (input) => {
|
|
4463
|
+
ensureSpawnHelperExecutable();
|
|
4411
4464
|
const { cols, rows } = ptyDimensions();
|
|
4412
4465
|
try {
|
|
4413
4466
|
return spawn$1(input.command, [...input.args], {
|
|
@@ -4594,7 +4647,8 @@ const runAndroidBuild = (input) => Effect.gen(function* () {
|
|
|
4594
4647
|
const credentials = input.credentialsSource === "local" ? yield* loadLocalAndroidCredentials({ projectRoot }) : yield* downloadAndroidCredentials(api, {
|
|
4595
4648
|
projectId,
|
|
4596
4649
|
applicationIdentifier,
|
|
4597
|
-
tempDir
|
|
4650
|
+
tempDir,
|
|
4651
|
+
buildProfile: input.profileName
|
|
4598
4652
|
});
|
|
4599
4653
|
yield* runStep({
|
|
4600
4654
|
command: "bunx",
|
|
@@ -5913,7 +5967,8 @@ const buildReserveCommon = (input) => ({
|
|
|
5913
5967
|
...input.buildNumber === void 0 ? {} : { buildNumber: input.buildNumber },
|
|
5914
5968
|
...input.gitContext.ref === void 0 ? {} : { gitRef: input.gitContext.ref },
|
|
5915
5969
|
...input.gitContext.commit === void 0 ? {} : { gitCommit: input.gitContext.commit },
|
|
5916
|
-
...input.message === void 0 ? {} : { message: input.message }
|
|
5970
|
+
...input.message === void 0 ? {} : { message: input.message },
|
|
5971
|
+
...input.fingerprintHash === void 0 ? {} : { fingerprintHash: input.fingerprintHash }
|
|
5917
5972
|
});
|
|
5918
5973
|
const callReserve = (api, input) => {
|
|
5919
5974
|
const common = buildReserveCommon(input);
|
|
@@ -6407,6 +6462,26 @@ const pullEnvVars = (api, { projectId, environment }) => {
|
|
|
6407
6462
|
} }).pipe(Effect.map((result) => Object.fromEntries(result.items.map((item) => [item.key, item.value]))), Effect.mapError((cause) => new EnvExportError({ message: `Failed to export environment variables for "${environment}": ${String(cause)}` })));
|
|
6408
6463
|
};
|
|
6409
6464
|
|
|
6465
|
+
//#endregion
|
|
6466
|
+
//#region src/lib/fingerprint.ts
|
|
6467
|
+
var FingerprintError = class extends Data.TaggedError("FingerprintError") {};
|
|
6468
|
+
const runFingerprintFull = (projectRoot) => Effect.gen(function* () {
|
|
6469
|
+
const cmd = Command.make("bunx", "@expo/fingerprint", projectRoot).pipe(Command.workingDirectory(projectRoot));
|
|
6470
|
+
const stdout = yield* Command.string(cmd).pipe(Effect.mapError((cause) => new FingerprintError({ message: `Failed to run "@expo/fingerprint": ${cause.message}` })));
|
|
6471
|
+
const parsed = yield* Effect.try({
|
|
6472
|
+
try: () => JSON.parse(stdout),
|
|
6473
|
+
catch: () => new FingerprintError({ message: "Failed to parse @expo/fingerprint output as JSON." })
|
|
6474
|
+
});
|
|
6475
|
+
if (!isRecord(parsed)) return yield* new FingerprintError({ message: "@expo/fingerprint output was not a JSON object." });
|
|
6476
|
+
const { hash } = parsed;
|
|
6477
|
+
if (typeof hash !== "string" || hash.length === 0) return yield* new FingerprintError({ message: "@expo/fingerprint output did not contain a \"hash\" string field." });
|
|
6478
|
+
const sourcesRaw = parsed["sources"];
|
|
6479
|
+
return {
|
|
6480
|
+
hash,
|
|
6481
|
+
sources: Array.isArray(sourcesRaw) ? sourcesRaw : []
|
|
6482
|
+
};
|
|
6483
|
+
});
|
|
6484
|
+
|
|
6410
6485
|
//#endregion
|
|
6411
6486
|
//#region src/lib/git-context.ts
|
|
6412
6487
|
const runString = (cmd, cwd) => Command.string(Command.workingDirectory(cmd, cwd));
|
|
@@ -6670,26 +6745,6 @@ const ensureRepoClean = ({ projectRoot, allowDirty, label }) => Effect.gen(funct
|
|
|
6670
6745
|
if (!(yield* promptConfirm(`Continue ${label} with uncommitted changes?`, { initialValue: false }))) yield* new DirtyRepoError({ message: `${label} cancelled by user.` });
|
|
6671
6746
|
});
|
|
6672
6747
|
|
|
6673
|
-
//#endregion
|
|
6674
|
-
//#region src/lib/fingerprint.ts
|
|
6675
|
-
var FingerprintError = class extends Data.TaggedError("FingerprintError") {};
|
|
6676
|
-
const runFingerprintFull = (projectRoot) => Effect.gen(function* () {
|
|
6677
|
-
const cmd = Command.make("bunx", "@expo/fingerprint", projectRoot).pipe(Command.workingDirectory(projectRoot));
|
|
6678
|
-
const stdout = yield* Command.string(cmd).pipe(Effect.mapError((cause) => new FingerprintError({ message: `Failed to run "@expo/fingerprint": ${cause.message}` })));
|
|
6679
|
-
const parsed = yield* Effect.try({
|
|
6680
|
-
try: () => JSON.parse(stdout),
|
|
6681
|
-
catch: () => new FingerprintError({ message: "Failed to parse @expo/fingerprint output as JSON." })
|
|
6682
|
-
});
|
|
6683
|
-
if (!isRecord(parsed)) return yield* new FingerprintError({ message: "@expo/fingerprint output was not a JSON object." });
|
|
6684
|
-
const { hash } = parsed;
|
|
6685
|
-
if (typeof hash !== "string" || hash.length === 0) return yield* new FingerprintError({ message: "@expo/fingerprint output did not contain a \"hash\" string field." });
|
|
6686
|
-
const sourcesRaw = parsed["sources"];
|
|
6687
|
-
return {
|
|
6688
|
-
hash,
|
|
6689
|
-
sources: Array.isArray(sourcesRaw) ? sourcesRaw : []
|
|
6690
|
-
};
|
|
6691
|
-
});
|
|
6692
|
-
|
|
6693
6748
|
//#endregion
|
|
6694
6749
|
//#region src/lib/runtime-version.ts
|
|
6695
6750
|
const resolveRuntimeVersion = ({ raw, appVersion, projectRoot }) => Effect.gen(function* () {
|
|
@@ -6768,7 +6823,8 @@ const runAndroidPlatformBuild = (input) => Effect.gen(function* () {
|
|
|
6768
6823
|
applicationIdentifier,
|
|
6769
6824
|
envVars,
|
|
6770
6825
|
projectId,
|
|
6771
|
-
credentialsSource
|
|
6826
|
+
credentialsSource,
|
|
6827
|
+
profileName: profile.name
|
|
6772
6828
|
}),
|
|
6773
6829
|
target: androidProfile.format === "aab" ? {
|
|
6774
6830
|
platform: "android",
|
|
@@ -6869,6 +6925,7 @@ const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
6869
6925
|
...rawGitContext.commit === void 0 ? {} : { commit: rawGitContext.commit },
|
|
6870
6926
|
dirty: rawGitContext.dirty
|
|
6871
6927
|
};
|
|
6928
|
+
const fingerprintHash = yield* runFingerprintFull(userCwd).pipe(Effect.map((entry) => entry.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
6872
6929
|
const result = yield* reserveAndUpload(api, {
|
|
6873
6930
|
target,
|
|
6874
6931
|
projectId,
|
|
@@ -6879,6 +6936,7 @@ const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
6879
6936
|
bundleId,
|
|
6880
6937
|
gitContext,
|
|
6881
6938
|
...options.message === void 0 ? {} : { message: options.message },
|
|
6939
|
+
...fingerprintHash === void 0 ? {} : { fingerprintHash },
|
|
6882
6940
|
artifactPath: build.artifactPath,
|
|
6883
6941
|
sha256: build.sha256,
|
|
6884
6942
|
byteSize: build.byteSize
|
|
@@ -7766,6 +7824,7 @@ const runUploadWorkflow = (options) => Effect.gen(function* () {
|
|
|
7766
7824
|
...rawGitContext.commit === void 0 ? {} : { commit: rawGitContext.commit },
|
|
7767
7825
|
dirty: rawGitContext.dirty
|
|
7768
7826
|
};
|
|
7827
|
+
const fingerprintHash = yield* runFingerprintFull(projectRoot).pipe(Effect.map((entry) => entry.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
7769
7828
|
const result = yield* reserveAndUpload(api, {
|
|
7770
7829
|
target,
|
|
7771
7830
|
projectId,
|
|
@@ -7776,6 +7835,7 @@ const runUploadWorkflow = (options) => Effect.gen(function* () {
|
|
|
7776
7835
|
bundleId,
|
|
7777
7836
|
gitContext,
|
|
7778
7837
|
...options.message === void 0 ? {} : { message: options.message },
|
|
7838
|
+
...fingerprintHash === void 0 ? {} : { fingerprintHash },
|
|
7779
7839
|
artifactPath: options.artifactPath,
|
|
7780
7840
|
sha256,
|
|
7781
7841
|
byteSize
|
|
@@ -13615,7 +13675,8 @@ const publishPlatform = (params) => Effect.gen(function* () {
|
|
|
13615
13675
|
signature: params.signedPayload.signature,
|
|
13616
13676
|
certificateChain: params.signedPayload.certificateChain
|
|
13617
13677
|
} : {},
|
|
13618
|
-
...params.rolloutPercentage === void 0 ? {} : { rolloutPercentage: params.rolloutPercentage }
|
|
13678
|
+
...params.rolloutPercentage === void 0 ? {} : { rolloutPercentage: params.rolloutPercentage },
|
|
13679
|
+
...params.fingerprintHash === void 0 ? {} : { fingerprintHash: params.fingerprintHash }
|
|
13619
13680
|
} }).pipe(Effect.mapError((cause) => new UpdatePublishError({ message: `Failed to publish ${params.platform} update: ${formatCause(cause)}` })));
|
|
13620
13681
|
return {
|
|
13621
13682
|
platform: params.platform,
|
|
@@ -13664,6 +13725,7 @@ const runUpdatePublish = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
13664
13725
|
const sharedExportDir = options.inputDir === void 0 ? void 0 : path.resolve(projectRoot, options.inputDir);
|
|
13665
13726
|
const groupId = randomUUID();
|
|
13666
13727
|
const message = resolvedMessage ?? "Publish via better-update CLI";
|
|
13728
|
+
const fingerprintHash = yield* runFingerprintFull(projectRoot).pipe(Effect.map((result) => result.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
13667
13729
|
if ((yield* InteractiveMode).allow && !options.auto) {
|
|
13668
13730
|
if (!(yield* confirmPublishPreview({
|
|
13669
13731
|
branch,
|
|
@@ -13709,6 +13771,7 @@ const runUpdatePublish = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
13709
13771
|
platform,
|
|
13710
13772
|
signedPayload: signedPayloads[platform] ?? null,
|
|
13711
13773
|
rolloutPercentage: options.rolloutPercentage,
|
|
13774
|
+
fingerprintHash,
|
|
13712
13775
|
skipBundler: options.skipBundler,
|
|
13713
13776
|
noBytecode: options.noBytecode,
|
|
13714
13777
|
sourceMaps: options.sourceMaps
|