@better-update/cli 0.16.0 → 0.18.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 +306 -126
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -14,12 +14,13 @@ 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, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { 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";
|
|
21
21
|
import plistMod from "@expo/plist";
|
|
22
22
|
import { ExpoRunFormatter } from "@expo/xcpretty";
|
|
23
|
+
import ignore from "ignore";
|
|
23
24
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
24
25
|
import { getFormattedSerialNumber, getX509Certificate, parsePKCS12 } from "@expo/pkcs12";
|
|
25
26
|
import qrcode from "qrcode-terminal";
|
|
@@ -30,7 +31,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
30
31
|
|
|
31
32
|
//#endregion
|
|
32
33
|
//#region package.json
|
|
33
|
-
var version = "0.
|
|
34
|
+
var version = "0.18.0";
|
|
34
35
|
|
|
35
36
|
//#endregion
|
|
36
37
|
//#region src/lib/interactive-mode.ts
|
|
@@ -199,11 +200,11 @@ var NotAcceptable = class extends Schema.TaggedError()("NotAcceptable", { messag
|
|
|
199
200
|
//#endregion
|
|
200
201
|
//#region ../../packages/api/src/groups/android-application-identifiers.ts
|
|
201
202
|
const idParam$16 = HttpApiSchema.param("id", Schema.String);
|
|
202
|
-
const projectIdParam$
|
|
203
|
-
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({
|
|
204
205
|
title: "List Android application identifiers",
|
|
205
206
|
description: "List all Android package identifiers for a project"
|
|
206
|
-
}))).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({
|
|
207
208
|
title: "Create Android application identifier",
|
|
208
209
|
description: "Register an Android package name for a project"
|
|
209
210
|
}))).add(HttpApiEndpoint.del("delete")`/api/android-application-identifiers/${idParam$16}`.addSuccess(DeleteAndroidApplicationIdentifierResult).annotateContext(OpenApi.annotations({
|
|
@@ -611,11 +612,11 @@ const AssetUploadResult = Schema.Struct({
|
|
|
611
612
|
|
|
612
613
|
//#endregion
|
|
613
614
|
//#region ../../packages/api/src/groups/assets.ts
|
|
614
|
-
const hashParam = HttpApiSchema.param("hash", Schema.String);
|
|
615
|
+
const hashParam$1 = HttpApiSchema.param("hash", Schema.String);
|
|
615
616
|
var AssetsGroup = class extends HttpApiGroup.make("assets").add(HttpApiEndpoint.post("upload", "/api/assets/upload").setPayload(AssetUploadBody).addSuccess(AssetUploadResult, { status: 201 }).annotateContext(OpenApi.annotations({
|
|
616
617
|
title: "Upload assets",
|
|
617
618
|
description: "Upload asset files to R2 storage (deduplicated by content hash)"
|
|
618
|
-
}))).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({
|
|
619
620
|
title: "Finalize asset upload",
|
|
620
621
|
description: "Verify a directly uploaded asset in R2 and mark it available for updates"
|
|
621
622
|
}))).addError(BadRequest).addError(NotFound).addError(Forbidden).annotateContext(OpenApi.annotations({
|
|
@@ -720,7 +721,8 @@ const ResolveBuildCredentialsIosBody = Schema.Struct({
|
|
|
720
721
|
});
|
|
721
722
|
const ResolveBuildCredentialsAndroidBody = Schema.Struct({
|
|
722
723
|
platform: Schema.Literal("android"),
|
|
723
|
-
applicationIdentifier: AndroidPackageName
|
|
724
|
+
applicationIdentifier: AndroidPackageName,
|
|
725
|
+
buildProfile: Schema.optional(Schema.String.pipe(Schema.minLength(1), Schema.maxLength(120)))
|
|
724
726
|
});
|
|
725
727
|
const ResolveBuildCredentialsBody = Schema.Union(ResolveBuildCredentialsIosBody, ResolveBuildCredentialsAndroidBody);
|
|
726
728
|
const IosBuildDistributionCertificate = Schema.Struct({
|
|
@@ -776,8 +778,8 @@ const ResolveBuildCredentialsResult = Schema.Union(ResolveBuildCredentialsIosRes
|
|
|
776
778
|
|
|
777
779
|
//#endregion
|
|
778
780
|
//#region ../../packages/api/src/groups/build-credentials.ts
|
|
779
|
-
const projectIdParam$
|
|
780
|
-
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({
|
|
781
783
|
title: "Resolve build credentials",
|
|
782
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."
|
|
783
785
|
}))).addError(NotFound).addError(BadRequest).addError(Forbidden).annotateContext(OpenApi.annotations({
|
|
@@ -788,6 +790,7 @@ var BuildCredentialsGroup = class extends HttpApiGroup.make("buildCredentials").
|
|
|
788
790
|
//#endregion
|
|
789
791
|
//#region ../../packages/api/src/domain/build.ts
|
|
790
792
|
const Distribution = Schema.Literal("app-store", "ad-hoc", "development", "enterprise", "simulator", "play-store", "direct");
|
|
793
|
+
const BuildAudience = Schema.Literal("internal", "store");
|
|
791
794
|
const ArtifactFormat = Schema.Literal("ipa", "apk", "aab", "tar.gz");
|
|
792
795
|
const Sha256Hex = Schema.String.pipe(Schema.pattern(/^[a-fA-F0-9]{64}$/u), Schema.maxLength(64));
|
|
793
796
|
const CreateBuildCommonFields = {
|
|
@@ -804,6 +807,7 @@ const CreateBuildCommonFields = {
|
|
|
804
807
|
key: Schema.String,
|
|
805
808
|
value: Schema.Unknown
|
|
806
809
|
})),
|
|
810
|
+
fingerprintHash: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
807
811
|
sha256: Sha256Hex,
|
|
808
812
|
byteSize: Schema.Number.pipe(Schema.nonNegative())
|
|
809
813
|
};
|
|
@@ -821,6 +825,7 @@ var Build = class extends Schema.Class("Build")({
|
|
|
821
825
|
gitCommit: Schema.NullOr(Schema.String),
|
|
822
826
|
message: Schema.NullOr(Schema.String),
|
|
823
827
|
metadataJson: Schema.String,
|
|
828
|
+
fingerprintHash: Schema.NullOr(Schema.String),
|
|
824
829
|
createdAt: DateTimeString
|
|
825
830
|
}) {};
|
|
826
831
|
var BuildArtifact = class extends Schema.Class("BuildArtifact")({
|
|
@@ -872,6 +877,7 @@ const ListBuildsParams = Schema.Struct({
|
|
|
872
877
|
profile: Schema.optional(Schema.String),
|
|
873
878
|
runtimeVersion: Schema.optional(Schema.String),
|
|
874
879
|
distribution: Schema.optional(Distribution),
|
|
880
|
+
audience: Schema.optional(BuildAudience),
|
|
875
881
|
...PaginationParams.fields,
|
|
876
882
|
sort: Schema.optional(BuildSort)
|
|
877
883
|
});
|
|
@@ -1244,6 +1250,108 @@ var EnvVarsGroup = class extends HttpApiGroup.make("env-vars").add(HttpApiEndpoi
|
|
|
1244
1250
|
description: "Manage environment variables for project builds and deployments"
|
|
1245
1251
|
})) {};
|
|
1246
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
|
+
|
|
1247
1355
|
//#endregion
|
|
1248
1356
|
//#region ../../packages/api/src/domain/google-service-account-key.ts
|
|
1249
1357
|
var GoogleServiceAccountKey = class extends Schema.Class("GoogleServiceAccountKey")({
|
|
@@ -1432,83 +1540,6 @@ var ProjectsGroup = class extends HttpApiGroup.make("projects").add(HttpApiEndpo
|
|
|
1432
1540
|
description: "Project management endpoints"
|
|
1433
1541
|
})) {};
|
|
1434
1542
|
|
|
1435
|
-
//#endregion
|
|
1436
|
-
//#region ../../packages/api/src/domain/update.ts
|
|
1437
|
-
var Update = class extends Schema.Class("Update")({
|
|
1438
|
-
id: Id,
|
|
1439
|
-
branchId: Id,
|
|
1440
|
-
runtimeVersion: Schema.String,
|
|
1441
|
-
platform: Platform,
|
|
1442
|
-
message: Schema.String,
|
|
1443
|
-
metadataJson: Schema.String,
|
|
1444
|
-
extraJson: Schema.NullOr(Schema.String),
|
|
1445
|
-
groupId: Schema.String,
|
|
1446
|
-
rolloutPercentage: Schema.Number,
|
|
1447
|
-
isRollback: Schema.Boolean,
|
|
1448
|
-
signature: Schema.NullOr(Schema.String),
|
|
1449
|
-
certificateChain: Schema.NullOr(Schema.String),
|
|
1450
|
-
manifestBody: Schema.NullOr(Schema.String),
|
|
1451
|
-
directiveBody: Schema.NullOr(Schema.String),
|
|
1452
|
-
createdAt: DateTimeString
|
|
1453
|
-
}) {};
|
|
1454
|
-
const UpdateSortColumn = Schema.Literal("createdAt", "runtimeVersion", "platform", "rolloutPercentage");
|
|
1455
|
-
/**
|
|
1456
|
-
* Sort param: column name optionally prefixed with `-` for descending.
|
|
1457
|
-
* Example: `runtimeVersion` (asc), `-createdAt` (desc).
|
|
1458
|
-
*/
|
|
1459
|
-
const UpdateSort = Schema.Union(UpdateSortColumn, Schema.TemplateLiteral("-", UpdateSortColumn));
|
|
1460
|
-
const ListUpdatesParams = Schema.Struct({
|
|
1461
|
-
projectId: Id,
|
|
1462
|
-
branchId: Schema.optional(Id),
|
|
1463
|
-
platform: Schema.optional(Platform),
|
|
1464
|
-
...PaginationParams.fields,
|
|
1465
|
-
sort: Schema.optional(UpdateSort)
|
|
1466
|
-
});
|
|
1467
|
-
const AssetRef = Schema.Struct({
|
|
1468
|
-
hash: Schema.String,
|
|
1469
|
-
key: Schema.String,
|
|
1470
|
-
isLaunch: Schema.Boolean,
|
|
1471
|
-
contentChecksum: Schema.optional(Schema.String)
|
|
1472
|
-
});
|
|
1473
|
-
const CreateUpdateBody = Schema.Struct({
|
|
1474
|
-
branch: Schema.String.pipe(Schema.minLength(1)),
|
|
1475
|
-
slug: Schema.String.pipe(Schema.minLength(1)),
|
|
1476
|
-
runtimeVersion: Schema.String.pipe(Schema.minLength(1)),
|
|
1477
|
-
platform: Platform,
|
|
1478
|
-
message: Schema.String,
|
|
1479
|
-
groupId: Schema.String.pipe(Schema.minLength(1)),
|
|
1480
|
-
metadata: Schema.Record({
|
|
1481
|
-
key: Schema.String,
|
|
1482
|
-
value: Schema.Unknown
|
|
1483
|
-
}),
|
|
1484
|
-
extra: Schema.optional(Schema.Record({
|
|
1485
|
-
key: Schema.String,
|
|
1486
|
-
value: Schema.Unknown
|
|
1487
|
-
})),
|
|
1488
|
-
assets: Schema.Array(AssetRef),
|
|
1489
|
-
manifestBody: Schema.optional(Schema.String),
|
|
1490
|
-
directiveBody: Schema.optional(Schema.String),
|
|
1491
|
-
isRollback: Schema.optional(Schema.Boolean),
|
|
1492
|
-
signature: Schema.optional(Schema.String),
|
|
1493
|
-
certificateChain: Schema.optional(Schema.String),
|
|
1494
|
-
rolloutPercentage: Schema.optional(Schema.Number.pipe(Schema.int(), Schema.between(1, 100)))
|
|
1495
|
-
});
|
|
1496
|
-
const RepublishBody = Schema.Struct({
|
|
1497
|
-
sourceUpdateId: Schema.optional(Id),
|
|
1498
|
-
sourceGroupId: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1499
|
-
destinationBranchId: Schema.optional(Id),
|
|
1500
|
-
destinationChannel: Schema.optional(Schema.String.pipe(Schema.minLength(1))),
|
|
1501
|
-
message: Schema.optional(Schema.String),
|
|
1502
|
-
signedUpdates: Schema.optional(Schema.Array(Schema.Struct({
|
|
1503
|
-
sourceUpdateId: Id,
|
|
1504
|
-
manifestBody: Schema.String.pipe(Schema.minLength(1)),
|
|
1505
|
-
signature: Schema.String.pipe(Schema.minLength(1)),
|
|
1506
|
-
certificateChain: Schema.String.pipe(Schema.minLength(1))
|
|
1507
|
-
})))
|
|
1508
|
-
});
|
|
1509
|
-
const RepublishResult = Schema.Struct({ updates: Schema.Array(Update) });
|
|
1510
|
-
const DeleteUpdateResult = Schema.Struct({ deleted: Schema.Number });
|
|
1511
|
-
|
|
1512
1543
|
//#endregion
|
|
1513
1544
|
//#region ../../packages/api/src/groups/updates.ts
|
|
1514
1545
|
const idParam$1 = HttpApiSchema.param("id", Schema.String);
|
|
@@ -1527,6 +1558,12 @@ var UpdatesGroup = class extends HttpApiGroup.make("updates").add(HttpApiEndpoin
|
|
|
1527
1558
|
}))).add(HttpApiEndpoint.get("get")`/api/updates/${idParam$1}`.addSuccess(Update).annotateContext(OpenApi.annotations({
|
|
1528
1559
|
title: "Get update",
|
|
1529
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"
|
|
1530
1567
|
}))).add(HttpApiEndpoint.del("deleteGroup")`/api/updates/${groupIdParam}`.addSuccess(DeleteUpdateResult).annotateContext(OpenApi.annotations({
|
|
1531
1568
|
title: "Delete update group",
|
|
1532
1569
|
description: "Delete all updates in a group (paired iOS + Android updates)"
|
|
@@ -1604,7 +1641,7 @@ var WebhooksGroup = class extends HttpApiGroup.make("webhooks").add(HttpApiEndpo
|
|
|
1604
1641
|
|
|
1605
1642
|
//#endregion
|
|
1606
1643
|
//#region ../../packages/api/src/api.ts
|
|
1607
|
-
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({
|
|
1608
1645
|
title: "Better Update Management API",
|
|
1609
1646
|
version: "1.0.0",
|
|
1610
1647
|
description: "Management API for OTA update publishing, deployment, and analytics"
|
|
@@ -1665,6 +1702,7 @@ var InvalidArgumentError = class extends Data.TaggedError("InvalidArgumentError"
|
|
|
1665
1702
|
var InteractiveProhibitedError = class extends Data.TaggedError("InteractiveProhibitedError") {};
|
|
1666
1703
|
var CredentialsJsonError = class extends Data.TaggedError("CredentialsJsonError") {};
|
|
1667
1704
|
var DirtyRepoError = class extends Data.TaggedError("DirtyRepoError") {};
|
|
1705
|
+
var StagingError = class extends Data.TaggedError("StagingError") {};
|
|
1668
1706
|
|
|
1669
1707
|
//#endregion
|
|
1670
1708
|
//#region src/lib/format-error.ts
|
|
@@ -4148,7 +4186,8 @@ const downloadAndroidCredentials = (api, options) => Effect.gen(function* () {
|
|
|
4148
4186
|
path: { projectId: options.projectId },
|
|
4149
4187
|
payload: {
|
|
4150
4188
|
platform: "android",
|
|
4151
|
-
applicationIdentifier: options.applicationIdentifier
|
|
4189
|
+
applicationIdentifier: options.applicationIdentifier,
|
|
4190
|
+
...options.buildProfile === void 0 ? {} : { buildProfile: options.buildProfile }
|
|
4152
4191
|
}
|
|
4153
4192
|
}).pipe(Effect.mapError((cause) => resolveErrorToMissingCredentials(cause, "android")));
|
|
4154
4193
|
if (resolved.platform !== "android") return yield* Effect.fail(new MissingCredentialsError({
|
|
@@ -4592,7 +4631,8 @@ const runAndroidBuild = (input) => Effect.gen(function* () {
|
|
|
4592
4631
|
const credentials = input.credentialsSource === "local" ? yield* loadLocalAndroidCredentials({ projectRoot }) : yield* downloadAndroidCredentials(api, {
|
|
4593
4632
|
projectId,
|
|
4594
4633
|
applicationIdentifier,
|
|
4595
|
-
tempDir
|
|
4634
|
+
tempDir,
|
|
4635
|
+
buildProfile: input.profileName
|
|
4596
4636
|
});
|
|
4597
4637
|
yield* runStep({
|
|
4598
4638
|
command: "bunx",
|
|
@@ -5911,7 +5951,8 @@ const buildReserveCommon = (input) => ({
|
|
|
5911
5951
|
...input.buildNumber === void 0 ? {} : { buildNumber: input.buildNumber },
|
|
5912
5952
|
...input.gitContext.ref === void 0 ? {} : { gitRef: input.gitContext.ref },
|
|
5913
5953
|
...input.gitContext.commit === void 0 ? {} : { gitCommit: input.gitContext.commit },
|
|
5914
|
-
...input.message === void 0 ? {} : { message: input.message }
|
|
5954
|
+
...input.message === void 0 ? {} : { message: input.message },
|
|
5955
|
+
...input.fingerprintHash === void 0 ? {} : { fingerprintHash: input.fingerprintHash }
|
|
5915
5956
|
});
|
|
5916
5957
|
const callReserve = (api, input) => {
|
|
5917
5958
|
const common = buildReserveCommon(input);
|
|
@@ -6405,6 +6446,26 @@ const pullEnvVars = (api, { projectId, environment }) => {
|
|
|
6405
6446
|
} }).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)}` })));
|
|
6406
6447
|
};
|
|
6407
6448
|
|
|
6449
|
+
//#endregion
|
|
6450
|
+
//#region src/lib/fingerprint.ts
|
|
6451
|
+
var FingerprintError = class extends Data.TaggedError("FingerprintError") {};
|
|
6452
|
+
const runFingerprintFull = (projectRoot) => Effect.gen(function* () {
|
|
6453
|
+
const cmd = Command.make("bunx", "@expo/fingerprint", projectRoot).pipe(Command.workingDirectory(projectRoot));
|
|
6454
|
+
const stdout = yield* Command.string(cmd).pipe(Effect.mapError((cause) => new FingerprintError({ message: `Failed to run "@expo/fingerprint": ${cause.message}` })));
|
|
6455
|
+
const parsed = yield* Effect.try({
|
|
6456
|
+
try: () => JSON.parse(stdout),
|
|
6457
|
+
catch: () => new FingerprintError({ message: "Failed to parse @expo/fingerprint output as JSON." })
|
|
6458
|
+
});
|
|
6459
|
+
if (!isRecord(parsed)) return yield* new FingerprintError({ message: "@expo/fingerprint output was not a JSON object." });
|
|
6460
|
+
const { hash } = parsed;
|
|
6461
|
+
if (typeof hash !== "string" || hash.length === 0) return yield* new FingerprintError({ message: "@expo/fingerprint output did not contain a \"hash\" string field." });
|
|
6462
|
+
const sourcesRaw = parsed["sources"];
|
|
6463
|
+
return {
|
|
6464
|
+
hash,
|
|
6465
|
+
sources: Array.isArray(sourcesRaw) ? sourcesRaw : []
|
|
6466
|
+
};
|
|
6467
|
+
});
|
|
6468
|
+
|
|
6408
6469
|
//#endregion
|
|
6409
6470
|
//#region src/lib/git-context.ts
|
|
6410
6471
|
const runString = (cmd, cwd) => Command.string(Command.workingDirectory(cmd, cwd));
|
|
@@ -6520,6 +6581,131 @@ const detectPlatform = (explicit, config) => Effect.gen(function* () {
|
|
|
6520
6581
|
})));
|
|
6521
6582
|
});
|
|
6522
6583
|
|
|
6584
|
+
//#endregion
|
|
6585
|
+
//#region src/lib/project-staging.ts
|
|
6586
|
+
const LOCKFILES = [
|
|
6587
|
+
["bun.lock", "bun"],
|
|
6588
|
+
["bun.lockb", "bun"],
|
|
6589
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
6590
|
+
["yarn.lock", "yarn"],
|
|
6591
|
+
["package-lock.json", "npm"]
|
|
6592
|
+
];
|
|
6593
|
+
/**
|
|
6594
|
+
* Paths never copied into staging — covers generated native build outputs and
|
|
6595
|
+
* dependency dirs that must be reinstalled fresh in staging.
|
|
6596
|
+
*/
|
|
6597
|
+
const ALWAYS_IGNORE = [
|
|
6598
|
+
"node_modules",
|
|
6599
|
+
".git",
|
|
6600
|
+
"ios/build",
|
|
6601
|
+
"ios/Pods",
|
|
6602
|
+
"ios/DerivedData",
|
|
6603
|
+
"android/build",
|
|
6604
|
+
"android/app/build",
|
|
6605
|
+
"android/.gradle",
|
|
6606
|
+
"android/.kotlin",
|
|
6607
|
+
".expo",
|
|
6608
|
+
".gradle",
|
|
6609
|
+
".turbo",
|
|
6610
|
+
"dist"
|
|
6611
|
+
];
|
|
6612
|
+
const findLockfile = (fs, dir) => Effect.gen(function* () {
|
|
6613
|
+
for (const [name, pm] of LOCKFILES) if (yield* fs.exists(path.join(dir, name)).pipe(Effect.catchAll(() => Effect.succeed(false)))) return pm;
|
|
6614
|
+
});
|
|
6615
|
+
const walkUpForLockfile = (startCwd, dir) => Effect.gen(function* () {
|
|
6616
|
+
const pm = yield* findLockfile(yield* FileSystem.FileSystem, dir);
|
|
6617
|
+
if (pm !== void 0) return {
|
|
6618
|
+
workspaceRoot: dir,
|
|
6619
|
+
packageManager: pm
|
|
6620
|
+
};
|
|
6621
|
+
const parent = path.dirname(dir);
|
|
6622
|
+
if (parent === dir) return {
|
|
6623
|
+
workspaceRoot: startCwd,
|
|
6624
|
+
packageManager: "bun"
|
|
6625
|
+
};
|
|
6626
|
+
return yield* walkUpForLockfile(startCwd, parent);
|
|
6627
|
+
});
|
|
6628
|
+
/**
|
|
6629
|
+
* Walk up from `cwd` to the first ancestor directory containing a lockfile.
|
|
6630
|
+
* That directory is the install root (monorepo workspace root or the app dir
|
|
6631
|
+
* itself in single-app layouts). Defaults to `cwd` + bun when no lockfile is
|
|
6632
|
+
* found anywhere up to the volume root.
|
|
6633
|
+
*/
|
|
6634
|
+
const detectWorkspaceRoot = (cwd) => walkUpForLockfile(cwd, cwd);
|
|
6635
|
+
/**
|
|
6636
|
+
* Build an `Ignore` matcher for the workspace root. `.easignore` REPLACES
|
|
6637
|
+
* `.gitignore` when present (matches EAS semantics); otherwise `.gitignore`
|
|
6638
|
+
* is layered on top of the always-ignore baseline.
|
|
6639
|
+
*/
|
|
6640
|
+
const buildIgnoreInstance = (workspaceRoot) => Effect.gen(function* () {
|
|
6641
|
+
const fs = yield* FileSystem.FileSystem;
|
|
6642
|
+
const ig = ignore();
|
|
6643
|
+
ig.add([...ALWAYS_IGNORE]);
|
|
6644
|
+
const easignorePath = path.join(workspaceRoot, ".easignore");
|
|
6645
|
+
if (yield* fs.exists(easignorePath).pipe(Effect.catchAll(() => Effect.succeed(false)))) {
|
|
6646
|
+
const content = yield* fs.readFileString(easignorePath).pipe(Effect.catchAll(() => Effect.succeed("")));
|
|
6647
|
+
ig.add(content);
|
|
6648
|
+
return ig;
|
|
6649
|
+
}
|
|
6650
|
+
const gitignorePath = path.join(workspaceRoot, ".gitignore");
|
|
6651
|
+
if (yield* fs.exists(gitignorePath).pipe(Effect.catchAll(() => Effect.succeed(false)))) {
|
|
6652
|
+
const content = yield* fs.readFileString(gitignorePath).pipe(Effect.catchAll(() => Effect.succeed("")));
|
|
6653
|
+
ig.add(content);
|
|
6654
|
+
}
|
|
6655
|
+
return ig;
|
|
6656
|
+
});
|
|
6657
|
+
const copyProjectTree = (params) => Effect.tryPromise({
|
|
6658
|
+
try: async () => {
|
|
6659
|
+
await promises.cp(params.source, params.dest, {
|
|
6660
|
+
recursive: true,
|
|
6661
|
+
dereference: false,
|
|
6662
|
+
filter: (src) => {
|
|
6663
|
+
const rel = path.relative(params.source, src);
|
|
6664
|
+
if (rel === "") return true;
|
|
6665
|
+
const posixRel = rel.split(path.sep).join("/");
|
|
6666
|
+
return !params.ig.ignores(posixRel);
|
|
6667
|
+
}
|
|
6668
|
+
});
|
|
6669
|
+
},
|
|
6670
|
+
catch: (cause) => new StagingError({ message: `Failed to copy project to staging dir: ${formatCause(cause)}` })
|
|
6671
|
+
});
|
|
6672
|
+
const runInstall = (params) => runStep({
|
|
6673
|
+
command: params.packageManager,
|
|
6674
|
+
args: ["install"],
|
|
6675
|
+
cwd: params.stagingRoot,
|
|
6676
|
+
env: params.env
|
|
6677
|
+
}, `${params.packageManager} install`);
|
|
6678
|
+
/**
|
|
6679
|
+
* Copy the user's project (or workspace root, for monorepos) into a fresh
|
|
6680
|
+
* directory inside `tempDir`, then run `<pm> install` there. The build then
|
|
6681
|
+
* runs entirely against the staged copy — the user's working tree stays clean
|
|
6682
|
+
* regardless of what `expo prebuild`, `pod install`, or `gradlew` write.
|
|
6683
|
+
*/
|
|
6684
|
+
const prepareStagingProject = (input) => Effect.gen(function* () {
|
|
6685
|
+
const runtime = yield* CliRuntime;
|
|
6686
|
+
const { workspaceRoot, packageManager } = yield* detectWorkspaceRoot(input.userCwd);
|
|
6687
|
+
const relAppPath = path.relative(workspaceRoot, input.userCwd);
|
|
6688
|
+
const stagingRoot = path.join(input.tempDir, "project");
|
|
6689
|
+
const projectRoot = relAppPath === "" ? stagingRoot : path.join(stagingRoot, relAppPath);
|
|
6690
|
+
yield* Console.log(`Staging build into ${stagingRoot}${relAppPath === "" ? "" : ` (app: ${relAppPath})`}`);
|
|
6691
|
+
yield* copyProjectTree({
|
|
6692
|
+
source: workspaceRoot,
|
|
6693
|
+
dest: stagingRoot,
|
|
6694
|
+
ig: yield* buildIgnoreInstance(workspaceRoot)
|
|
6695
|
+
});
|
|
6696
|
+
yield* runInstall({
|
|
6697
|
+
stagingRoot,
|
|
6698
|
+
packageManager,
|
|
6699
|
+
env: yield* runtime.commandEnvironment(input.envVars)
|
|
6700
|
+
});
|
|
6701
|
+
return {
|
|
6702
|
+
stagingRoot,
|
|
6703
|
+
projectRoot,
|
|
6704
|
+
packageManager,
|
|
6705
|
+
relAppPath
|
|
6706
|
+
};
|
|
6707
|
+
});
|
|
6708
|
+
|
|
6523
6709
|
//#endregion
|
|
6524
6710
|
//#region src/lib/repo-clean.ts
|
|
6525
6711
|
const MAX_FILES_SHOWN = 10;
|
|
@@ -6543,26 +6729,6 @@ const ensureRepoClean = ({ projectRoot, allowDirty, label }) => Effect.gen(funct
|
|
|
6543
6729
|
if (!(yield* promptConfirm(`Continue ${label} with uncommitted changes?`, { initialValue: false }))) yield* new DirtyRepoError({ message: `${label} cancelled by user.` });
|
|
6544
6730
|
});
|
|
6545
6731
|
|
|
6546
|
-
//#endregion
|
|
6547
|
-
//#region src/lib/fingerprint.ts
|
|
6548
|
-
var FingerprintError = class extends Data.TaggedError("FingerprintError") {};
|
|
6549
|
-
const runFingerprintFull = (projectRoot) => Effect.gen(function* () {
|
|
6550
|
-
const cmd = Command.make("bunx", "@expo/fingerprint", projectRoot).pipe(Command.workingDirectory(projectRoot));
|
|
6551
|
-
const stdout = yield* Command.string(cmd).pipe(Effect.mapError((cause) => new FingerprintError({ message: `Failed to run "@expo/fingerprint": ${cause.message}` })));
|
|
6552
|
-
const parsed = yield* Effect.try({
|
|
6553
|
-
try: () => JSON.parse(stdout),
|
|
6554
|
-
catch: () => new FingerprintError({ message: "Failed to parse @expo/fingerprint output as JSON." })
|
|
6555
|
-
});
|
|
6556
|
-
if (!isRecord(parsed)) return yield* new FingerprintError({ message: "@expo/fingerprint output was not a JSON object." });
|
|
6557
|
-
const { hash } = parsed;
|
|
6558
|
-
if (typeof hash !== "string" || hash.length === 0) return yield* new FingerprintError({ message: "@expo/fingerprint output did not contain a \"hash\" string field." });
|
|
6559
|
-
const sourcesRaw = parsed["sources"];
|
|
6560
|
-
return {
|
|
6561
|
-
hash,
|
|
6562
|
-
sources: Array.isArray(sourcesRaw) ? sourcesRaw : []
|
|
6563
|
-
};
|
|
6564
|
-
});
|
|
6565
|
-
|
|
6566
6732
|
//#endregion
|
|
6567
6733
|
//#region src/lib/runtime-version.ts
|
|
6568
6734
|
const resolveRuntimeVersion = ({ raw, appVersion, projectRoot }) => Effect.gen(function* () {
|
|
@@ -6641,7 +6807,8 @@ const runAndroidPlatformBuild = (input) => Effect.gen(function* () {
|
|
|
6641
6807
|
applicationIdentifier,
|
|
6642
6808
|
envVars,
|
|
6643
6809
|
projectId,
|
|
6644
|
-
credentialsSource
|
|
6810
|
+
credentialsSource,
|
|
6811
|
+
profileName: profile.name
|
|
6645
6812
|
}),
|
|
6646
6813
|
target: androidProfile.format === "aab" ? {
|
|
6647
6814
|
platform: "android",
|
|
@@ -6669,35 +6836,40 @@ const resolveProfileName = (projectRoot, requested) => Effect.gen(function* () {
|
|
|
6669
6836
|
});
|
|
6670
6837
|
const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
6671
6838
|
const api = yield* apiClient;
|
|
6672
|
-
const
|
|
6839
|
+
const userCwd = yield* (yield* CliRuntime).cwd;
|
|
6673
6840
|
yield* ensureRepoClean({
|
|
6674
|
-
projectRoot,
|
|
6841
|
+
projectRoot: userCwd,
|
|
6675
6842
|
allowDirty: options.allowDirty ?? false,
|
|
6676
6843
|
label: "build"
|
|
6677
6844
|
});
|
|
6678
|
-
const baseConfig = yield* readExpoConfig(
|
|
6845
|
+
const baseConfig = yield* readExpoConfig(userCwd);
|
|
6679
6846
|
const projectId = yield* extractProjectId(baseConfig);
|
|
6680
6847
|
const platform = yield* detectPlatform(options.platform, baseConfig);
|
|
6681
|
-
const profile = yield* readBuildProfile(
|
|
6848
|
+
const profile = yield* readBuildProfile(userCwd, yield* resolveProfileName(userCwd, options.profileName));
|
|
6682
6849
|
const envVars = yield* pullEnvVars(api, {
|
|
6683
6850
|
projectId,
|
|
6684
6851
|
environment: profile.environment
|
|
6685
6852
|
});
|
|
6686
6853
|
yield* applyAutoIncrement({
|
|
6687
|
-
projectRoot,
|
|
6854
|
+
projectRoot: userCwd,
|
|
6688
6855
|
platform,
|
|
6689
|
-
config: yield* readExpoConfig(
|
|
6856
|
+
config: yield* readExpoConfig(userCwd, envVars),
|
|
6690
6857
|
...platform === "ios" && profile.ios?.autoIncrement !== void 0 ? { iosMode: profile.ios.autoIncrement } : {},
|
|
6691
6858
|
...platform === "android" && profile.android?.autoIncrement !== void 0 ? { androidMode: profile.android.autoIncrement } : {}
|
|
6692
6859
|
});
|
|
6693
|
-
const appMeta = yield* readAppMeta(yield* readExpoConfig(
|
|
6860
|
+
const appMeta = yield* readAppMeta(yield* readExpoConfig(userCwd, envVars), platform);
|
|
6694
6861
|
const runtimeVersion = yield* resolveRuntimeVersion({
|
|
6695
6862
|
raw: appMeta.rawRuntimeVersion,
|
|
6696
6863
|
appVersion: appMeta.appVersion,
|
|
6697
|
-
projectRoot
|
|
6864
|
+
projectRoot: userCwd
|
|
6698
6865
|
});
|
|
6699
|
-
if (options.clearCache) yield* clearBuildCaches(
|
|
6866
|
+
if (options.clearCache) yield* clearBuildCaches(userCwd);
|
|
6700
6867
|
const tempDir = yield* acquireBuildTempDir;
|
|
6868
|
+
const staging = yield* prepareStagingProject({
|
|
6869
|
+
userCwd,
|
|
6870
|
+
tempDir,
|
|
6871
|
+
envVars
|
|
6872
|
+
});
|
|
6701
6873
|
yield* Console.log(`Building ${platform} artifact for profile "${profile.name}" (runtimeVersion=${runtimeVersion})`);
|
|
6702
6874
|
const { build, target, bundleId } = yield* runPlatformBuild({
|
|
6703
6875
|
api,
|
|
@@ -6707,14 +6879,14 @@ const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
6707
6879
|
appMeta,
|
|
6708
6880
|
envVars,
|
|
6709
6881
|
projectId,
|
|
6710
|
-
projectRoot,
|
|
6882
|
+
projectRoot: staging.projectRoot,
|
|
6711
6883
|
tempDir
|
|
6712
6884
|
});
|
|
6713
6885
|
yield* Console.log(`Artifact produced: ${build.artifactPath}`);
|
|
6714
6886
|
let exportedArtifactPath = void 0;
|
|
6715
6887
|
if (options.output !== void 0) {
|
|
6716
6888
|
const fs = yield* FileSystem.FileSystem;
|
|
6717
|
-
const outputPath = path.resolve(
|
|
6889
|
+
const outputPath = path.resolve(userCwd, options.output);
|
|
6718
6890
|
const outputDir = path.dirname(outputPath);
|
|
6719
6891
|
yield* fs.makeDirectory(outputDir, { recursive: true }).pipe(Effect.mapError((cause) => new BuildProfileError({ message: `Failed to create output directory: ${formatCause(cause)}` })));
|
|
6720
6892
|
yield* fs.copyFile(build.artifactPath, outputPath).pipe(Effect.mapError((cause) => new BuildProfileError({ message: `Failed to copy artifact to ${outputPath}: ${formatCause(cause)}` })));
|
|
@@ -6731,12 +6903,13 @@ const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
6731
6903
|
]);
|
|
6732
6904
|
return;
|
|
6733
6905
|
}
|
|
6734
|
-
const rawGitContext = yield* readGitContext(
|
|
6906
|
+
const rawGitContext = yield* readGitContext(userCwd);
|
|
6735
6907
|
const gitContext = {
|
|
6736
6908
|
...rawGitContext.ref === void 0 ? {} : { ref: rawGitContext.ref },
|
|
6737
6909
|
...rawGitContext.commit === void 0 ? {} : { commit: rawGitContext.commit },
|
|
6738
6910
|
dirty: rawGitContext.dirty
|
|
6739
6911
|
};
|
|
6912
|
+
const fingerprintHash = yield* runFingerprintFull(userCwd).pipe(Effect.map((entry) => entry.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
6740
6913
|
const result = yield* reserveAndUpload(api, {
|
|
6741
6914
|
target,
|
|
6742
6915
|
projectId,
|
|
@@ -6747,6 +6920,7 @@ const runBuildWorkflow = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
6747
6920
|
bundleId,
|
|
6748
6921
|
gitContext,
|
|
6749
6922
|
...options.message === void 0 ? {} : { message: options.message },
|
|
6923
|
+
...fingerprintHash === void 0 ? {} : { fingerprintHash },
|
|
6750
6924
|
artifactPath: build.artifactPath,
|
|
6751
6925
|
sha256: build.sha256,
|
|
6752
6926
|
byteSize: build.byteSize
|
|
@@ -6875,7 +7049,8 @@ const BUILD_EXIT_EXTRAS = {
|
|
|
6875
7049
|
PresignedUrlExpiredError: 7,
|
|
6876
7050
|
CompleteError: 7,
|
|
6877
7051
|
EnvExportError: 7,
|
|
6878
|
-
DirtyRepoError: 3
|
|
7052
|
+
DirtyRepoError: 3,
|
|
7053
|
+
StagingError: 6
|
|
6879
7054
|
};
|
|
6880
7055
|
const buildCommand = defineCommand({
|
|
6881
7056
|
meta: {
|
|
@@ -7633,6 +7808,7 @@ const runUploadWorkflow = (options) => Effect.gen(function* () {
|
|
|
7633
7808
|
...rawGitContext.commit === void 0 ? {} : { commit: rawGitContext.commit },
|
|
7634
7809
|
dirty: rawGitContext.dirty
|
|
7635
7810
|
};
|
|
7811
|
+
const fingerprintHash = yield* runFingerprintFull(projectRoot).pipe(Effect.map((entry) => entry.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
7636
7812
|
const result = yield* reserveAndUpload(api, {
|
|
7637
7813
|
target,
|
|
7638
7814
|
projectId,
|
|
@@ -7643,6 +7819,7 @@ const runUploadWorkflow = (options) => Effect.gen(function* () {
|
|
|
7643
7819
|
bundleId,
|
|
7644
7820
|
gitContext,
|
|
7645
7821
|
...options.message === void 0 ? {} : { message: options.message },
|
|
7822
|
+
...fingerprintHash === void 0 ? {} : { fingerprintHash },
|
|
7646
7823
|
artifactPath: options.artifactPath,
|
|
7647
7824
|
sha256,
|
|
7648
7825
|
byteSize
|
|
@@ -13482,7 +13659,8 @@ const publishPlatform = (params) => Effect.gen(function* () {
|
|
|
13482
13659
|
signature: params.signedPayload.signature,
|
|
13483
13660
|
certificateChain: params.signedPayload.certificateChain
|
|
13484
13661
|
} : {},
|
|
13485
|
-
...params.rolloutPercentage === void 0 ? {} : { rolloutPercentage: params.rolloutPercentage }
|
|
13662
|
+
...params.rolloutPercentage === void 0 ? {} : { rolloutPercentage: params.rolloutPercentage },
|
|
13663
|
+
...params.fingerprintHash === void 0 ? {} : { fingerprintHash: params.fingerprintHash }
|
|
13486
13664
|
} }).pipe(Effect.mapError((cause) => new UpdatePublishError({ message: `Failed to publish ${params.platform} update: ${formatCause(cause)}` })));
|
|
13487
13665
|
return {
|
|
13488
13666
|
platform: params.platform,
|
|
@@ -13531,6 +13709,7 @@ const runUpdatePublish = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
13531
13709
|
const sharedExportDir = options.inputDir === void 0 ? void 0 : path.resolve(projectRoot, options.inputDir);
|
|
13532
13710
|
const groupId = randomUUID();
|
|
13533
13711
|
const message = resolvedMessage ?? "Publish via better-update CLI";
|
|
13712
|
+
const fingerprintHash = yield* runFingerprintFull(projectRoot).pipe(Effect.map((result) => result.hash), Effect.catchAll(() => Effect.succeed(void 0)));
|
|
13534
13713
|
if ((yield* InteractiveMode).allow && !options.auto) {
|
|
13535
13714
|
if (!(yield* confirmPublishPreview({
|
|
13536
13715
|
branch,
|
|
@@ -13576,6 +13755,7 @@ const runUpdatePublish = (options) => Effect.scoped(Effect.gen(function* () {
|
|
|
13576
13755
|
platform,
|
|
13577
13756
|
signedPayload: signedPayloads[platform] ?? null,
|
|
13578
13757
|
rolloutPercentage: options.rolloutPercentage,
|
|
13758
|
+
fingerprintHash,
|
|
13579
13759
|
skipBundler: options.skipBundler,
|
|
13580
13760
|
noBytecode: options.noBytecode,
|
|
13581
13761
|
sourceMaps: options.sourceMaps
|