@layr-labs/ecloud-sdk 0.2.0-dev.2 → 0.2.0-dev.3
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/VERSION +2 -2
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +1 -1
- package/dist/billing.d.ts +1 -1
- package/dist/billing.js +2 -2
- package/dist/{chunk-2RORGPLX.js → chunk-OUCNETHL.js} +2 -2
- package/dist/chunk-OUCNETHL.js.map +1 -0
- package/dist/{chunk-ZEZS5CNB.js → chunk-QN7KAUOB.js} +106 -30
- package/dist/chunk-QN7KAUOB.js.map +1 -0
- package/dist/{chunk-4SKRNFKQ.js → chunk-R44OVMCY.js} +535 -105
- package/dist/chunk-R44OVMCY.js.map +1 -0
- package/dist/{compute-B_ibIORD.d.cts → compute-CF2HOXed.d.ts} +101 -15
- package/dist/{compute-gpepEsn3.d.ts → compute-CbmjA8kJ.d.cts} +101 -15
- package/dist/compute.cjs +850 -62
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.d.cts +2 -2
- package/dist/compute.d.ts +2 -2
- package/dist/compute.js +2 -2
- package/dist/{index-D-SUX3IG.d.ts → index-D2QufVB9.d.cts} +130 -6
- package/dist/{index-D-SUX3IG.d.cts → index-D2QufVB9.d.ts} +130 -6
- package/dist/index.cjs +989 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +334 -231
- package/dist/index.d.ts +334 -231
- package/dist/index.js +376 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-2RORGPLX.js.map +0 -1
- package/dist/chunk-4SKRNFKQ.js.map +0 -1
- package/dist/chunk-ZEZS5CNB.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -30,10 +30,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AuthRequiredError: () => AuthRequiredError,
|
|
34
|
+
BUILD_STATUS: () => BUILD_STATUS,
|
|
35
|
+
BadRequestError: () => BadRequestError,
|
|
36
|
+
BuildError: () => BuildError,
|
|
37
|
+
BuildFailedError: () => BuildFailedError,
|
|
38
|
+
ConflictError: () => ConflictError,
|
|
39
|
+
ForbiddenError: () => ForbiddenError,
|
|
33
40
|
NoopClient: () => NoopClient,
|
|
41
|
+
NotFoundError: () => NotFoundError,
|
|
34
42
|
PRIMARY_LANGUAGES: () => PRIMARY_LANGUAGES,
|
|
35
43
|
PostHogClient: () => PostHogClient,
|
|
44
|
+
TimeoutError: () => TimeoutError,
|
|
36
45
|
UserApiClient: () => UserApiClient,
|
|
46
|
+
addHexPrefix: () => addHexPrefix,
|
|
37
47
|
addMetric: () => addMetric,
|
|
38
48
|
addMetricWithDimensions: () => addMetricWithDimensions,
|
|
39
49
|
assertValidFilePath: () => assertValidFilePath,
|
|
@@ -43,6 +53,7 @@ __export(index_exports, {
|
|
|
43
53
|
createApp: () => createApp,
|
|
44
54
|
createAppEnvironment: () => createAppEnvironment,
|
|
45
55
|
createBillingModule: () => createBillingModule,
|
|
56
|
+
createBuildModule: () => createBuildModule,
|
|
46
57
|
createComputeModule: () => createComputeModule,
|
|
47
58
|
createECloudClient: () => createECloudClient,
|
|
48
59
|
createMetricsContext: () => createMetricsContext,
|
|
@@ -86,12 +97,15 @@ __export(index_exports, {
|
|
|
86
97
|
listStoredKeys: () => listStoredKeys,
|
|
87
98
|
logs: () => logs,
|
|
88
99
|
prepareDeploy: () => prepareDeploy,
|
|
100
|
+
prepareDeployFromVerifiableBuild: () => prepareDeployFromVerifiableBuild,
|
|
89
101
|
prepareUpgrade: () => prepareUpgrade,
|
|
102
|
+
prepareUpgradeFromVerifiableBuild: () => prepareUpgradeFromVerifiableBuild,
|
|
90
103
|
requirePrivateKey: () => requirePrivateKey,
|
|
91
104
|
sanitizeString: () => sanitizeString,
|
|
92
105
|
sanitizeURL: () => sanitizeURL,
|
|
93
106
|
sanitizeXURL: () => sanitizeXURL,
|
|
94
107
|
storePrivateKey: () => storePrivateKey,
|
|
108
|
+
stripHexPrefix: () => stripHexPrefix,
|
|
95
109
|
validateAppID: () => validateAppID,
|
|
96
110
|
validateAppName: () => validateAppName,
|
|
97
111
|
validateCreateAppParams: () => validateCreateAppParams,
|
|
@@ -117,6 +131,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
117
131
|
|
|
118
132
|
// src/client/modules/compute/app/index.ts
|
|
119
133
|
var import_viem9 = require("viem");
|
|
134
|
+
var import_accounts5 = require("viem/accounts");
|
|
120
135
|
|
|
121
136
|
// src/client/common/config/environment.ts
|
|
122
137
|
var SEPOLIA_CHAIN_ID = 11155111;
|
|
@@ -257,6 +272,7 @@ async function buildDockerImage(buildContext, dockerfilePath, tag, logger) {
|
|
|
257
272
|
tag,
|
|
258
273
|
"-f",
|
|
259
274
|
dockerfilePath,
|
|
275
|
+
"--load",
|
|
260
276
|
"--progress=plain",
|
|
261
277
|
buildContext
|
|
262
278
|
];
|
|
@@ -382,7 +398,7 @@ async function pullDockerImage(docker, imageTag, platform2 = "linux/amd64", logg
|
|
|
382
398
|
var child_process2 = __toESM(require("child_process"), 1);
|
|
383
399
|
var import_child_process = require("child_process");
|
|
384
400
|
var import_util2 = require("util");
|
|
385
|
-
var
|
|
401
|
+
var execFileAsync = (0, import_util2.promisify)(import_child_process.execFile);
|
|
386
402
|
async function pushDockerImage(docker, imageRef, logger) {
|
|
387
403
|
logger?.info?.(`Pushing image ${imageRef}...`);
|
|
388
404
|
return new Promise((resolve2, reject) => {
|
|
@@ -423,9 +439,9 @@ async function pushDockerImage(docker, imageRef, logger) {
|
|
|
423
439
|
if (!output.includes("digest:") && !output.includes("pushed") && !output.includes("Pushed")) {
|
|
424
440
|
logger?.debug?.("No clear success indicator in push output, verifying...");
|
|
425
441
|
}
|
|
426
|
-
logger?.info?.("Image push completed successfully");
|
|
427
442
|
try {
|
|
428
443
|
await verifyImageExists(imageRef, logger);
|
|
444
|
+
logger?.info?.("Image push completed successfully");
|
|
429
445
|
resolve2();
|
|
430
446
|
} catch (error) {
|
|
431
447
|
reject(error);
|
|
@@ -449,7 +465,7 @@ async function verifyImageExists(imageRef, logger) {
|
|
|
449
465
|
let retries = 5;
|
|
450
466
|
while (retries > 0) {
|
|
451
467
|
try {
|
|
452
|
-
await
|
|
468
|
+
await execFileAsync("docker", ["manifest", "inspect", imageRef], {
|
|
453
469
|
maxBuffer: 10 * 1024 * 1024,
|
|
454
470
|
timeout: 1e4
|
|
455
471
|
// 10 second timeout
|
|
@@ -923,10 +939,10 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
923
939
|
// src/client/common/registry/digest.ts
|
|
924
940
|
var child_process3 = __toESM(require("child_process"), 1);
|
|
925
941
|
var import_util3 = require("util");
|
|
926
|
-
var
|
|
942
|
+
var execFileAsync2 = (0, import_util3.promisify)(child_process3.execFile);
|
|
927
943
|
async function getImageDigestAndName(imageRef) {
|
|
928
944
|
try {
|
|
929
|
-
const { stdout } = await
|
|
945
|
+
const { stdout } = await execFileAsync2(
|
|
930
946
|
"docker",
|
|
931
947
|
["manifest", "inspect", imageRef],
|
|
932
948
|
{ maxBuffer: 10 * 1024 * 1024 }
|
|
@@ -966,7 +982,7 @@ function extractDigestFromMultiPlatform(manifest, imageRef) {
|
|
|
966
982
|
}
|
|
967
983
|
async function extractDigestFromSinglePlatform(manifest, imageRef) {
|
|
968
984
|
try {
|
|
969
|
-
const { stdout } = await
|
|
985
|
+
const { stdout } = await execFileAsync2("docker", ["inspect", imageRef], {
|
|
970
986
|
maxBuffer: 10 * 1024 * 1024
|
|
971
987
|
});
|
|
972
988
|
const inspectData = JSON.parse(stdout);
|
|
@@ -1264,6 +1280,67 @@ Please verify the image exists: docker manifest inspect ${finalImageRef}`
|
|
|
1264
1280
|
};
|
|
1265
1281
|
}
|
|
1266
1282
|
|
|
1283
|
+
// src/client/common/release/prebuilt.ts
|
|
1284
|
+
async function createReleaseFromImageDigest(options, logger) {
|
|
1285
|
+
const { imageRef, imageDigest, envFilePath, instanceType, environmentConfig, appId } = options;
|
|
1286
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(imageDigest)) {
|
|
1287
|
+
throw new Error(`imageDigest must be in format sha256:<64 hex>, got: ${imageDigest}`);
|
|
1288
|
+
}
|
|
1289
|
+
let publicEnv = {};
|
|
1290
|
+
let privateEnv = {};
|
|
1291
|
+
if (envFilePath) {
|
|
1292
|
+
logger.info("Parsing environment file...");
|
|
1293
|
+
const parsed = parseAndValidateEnvFile(envFilePath);
|
|
1294
|
+
publicEnv = parsed.public;
|
|
1295
|
+
privateEnv = parsed.private;
|
|
1296
|
+
} else {
|
|
1297
|
+
logger.info("Continuing without environment file");
|
|
1298
|
+
}
|
|
1299
|
+
publicEnv["EIGEN_MACHINE_TYPE_PUBLIC"] = instanceType;
|
|
1300
|
+
logger.info(`Instance type: ${instanceType}`);
|
|
1301
|
+
logger.info("Encrypting environment variables...");
|
|
1302
|
+
const { encryptionKey } = getKMSKeysForEnvironment(
|
|
1303
|
+
environmentConfig.name,
|
|
1304
|
+
environmentConfig.build
|
|
1305
|
+
);
|
|
1306
|
+
const protectedHeaders = getAppProtectedHeaders(appId);
|
|
1307
|
+
const privateEnvBytes = Buffer.from(JSON.stringify(privateEnv));
|
|
1308
|
+
const encryptedEnvStr = await encryptRSAOAEPAndAES256GCM(
|
|
1309
|
+
encryptionKey,
|
|
1310
|
+
privateEnvBytes,
|
|
1311
|
+
protectedHeaders
|
|
1312
|
+
);
|
|
1313
|
+
const digestHex = imageDigest.split(":")[1];
|
|
1314
|
+
const digestBytes = new Uint8Array(Buffer.from(digestHex, "hex"));
|
|
1315
|
+
if (digestBytes.length !== 32) {
|
|
1316
|
+
throw new Error(`Digest must be exactly 32 bytes, got ${digestBytes.length}`);
|
|
1317
|
+
}
|
|
1318
|
+
const registry = extractRegistryNameNoDocker(imageRef);
|
|
1319
|
+
return {
|
|
1320
|
+
rmsRelease: {
|
|
1321
|
+
artifacts: [{ digest: digestBytes, registry }],
|
|
1322
|
+
upgradeByTime: Math.floor(Date.now() / 1e3) + 3600
|
|
1323
|
+
},
|
|
1324
|
+
publicEnv: new Uint8Array(Buffer.from(JSON.stringify(publicEnv))),
|
|
1325
|
+
encryptedEnv: new Uint8Array(Buffer.from(encryptedEnvStr))
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function extractRegistryNameNoDocker(imageRef) {
|
|
1329
|
+
let name = imageRef;
|
|
1330
|
+
const tagIndex = name.lastIndexOf(":");
|
|
1331
|
+
if (tagIndex !== -1 && !name.substring(tagIndex + 1).includes("/")) {
|
|
1332
|
+
name = name.substring(0, tagIndex);
|
|
1333
|
+
}
|
|
1334
|
+
const digestIndex = name.indexOf("@");
|
|
1335
|
+
if (digestIndex !== -1) {
|
|
1336
|
+
name = name.substring(0, digestIndex);
|
|
1337
|
+
}
|
|
1338
|
+
if ([...name].filter((c) => c === "/").length === 1) {
|
|
1339
|
+
name = `docker.io/${name}`;
|
|
1340
|
+
}
|
|
1341
|
+
return name;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1267
1344
|
// src/client/common/contract/caller.ts
|
|
1268
1345
|
var import_accounts2 = require("viem/accounts");
|
|
1269
1346
|
|
|
@@ -2300,27 +2377,55 @@ var ERC7702Delegator_default = [
|
|
|
2300
2377
|
];
|
|
2301
2378
|
|
|
2302
2379
|
// src/client/common/contract/eip7702.ts
|
|
2380
|
+
var EXECUTE_BATCH_MODE = "0x0100000000000000000000000000000000000000000000000000000000000000";
|
|
2381
|
+
var GAS_LIMIT_BUFFER_PERCENTAGE = 20n;
|
|
2382
|
+
var GAS_PRICE_BUFFER_PERCENTAGE = 100n;
|
|
2383
|
+
function encodeExecuteBatchData(executions) {
|
|
2384
|
+
const encodedExecutions = (0, import_viem.encodeAbiParameters)(
|
|
2385
|
+
[
|
|
2386
|
+
{
|
|
2387
|
+
type: "tuple[]",
|
|
2388
|
+
components: [
|
|
2389
|
+
{ name: "target", type: "address" },
|
|
2390
|
+
{ name: "value", type: "uint256" },
|
|
2391
|
+
{ name: "callData", type: "bytes" }
|
|
2392
|
+
]
|
|
2393
|
+
}
|
|
2394
|
+
],
|
|
2395
|
+
[executions]
|
|
2396
|
+
);
|
|
2397
|
+
return (0, import_viem.encodeFunctionData)({
|
|
2398
|
+
abi: ERC7702Delegator_default,
|
|
2399
|
+
functionName: "execute",
|
|
2400
|
+
args: [EXECUTE_BATCH_MODE, encodedExecutions]
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2303
2403
|
async function estimateBatchGas(options) {
|
|
2304
|
-
const { publicClient, executions } = options;
|
|
2305
|
-
const
|
|
2306
|
-
const
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2404
|
+
const { publicClient, account, executions } = options;
|
|
2405
|
+
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2406
|
+
const [gasTipCap, block, estimatedGas] = await Promise.all([
|
|
2407
|
+
publicClient.estimateMaxPriorityFeePerGas(),
|
|
2408
|
+
publicClient.getBlock(),
|
|
2409
|
+
publicClient.estimateGas({
|
|
2410
|
+
account,
|
|
2411
|
+
to: account,
|
|
2412
|
+
data: executeBatchData
|
|
2413
|
+
})
|
|
2414
|
+
]);
|
|
2415
|
+
const baseFee = block.baseFeePerGas ?? 0n;
|
|
2416
|
+
const maxFeePerGas = (baseFee + gasTipCap) * (100n + GAS_PRICE_BUFFER_PERCENTAGE) / 100n;
|
|
2417
|
+
const gasLimit = estimatedGas * (100n + GAS_LIMIT_BUFFER_PERCENTAGE) / 100n;
|
|
2312
2418
|
const maxCostWei = gasLimit * maxFeePerGas;
|
|
2313
|
-
const maxCostEth = formatETH(maxCostWei);
|
|
2314
2419
|
return {
|
|
2315
2420
|
gasLimit,
|
|
2316
2421
|
maxFeePerGas,
|
|
2317
|
-
maxPriorityFeePerGas,
|
|
2422
|
+
maxPriorityFeePerGas: gasTipCap,
|
|
2318
2423
|
maxCostWei,
|
|
2319
|
-
maxCostEth
|
|
2424
|
+
maxCostEth: formatETH(maxCostWei)
|
|
2320
2425
|
};
|
|
2321
2426
|
}
|
|
2322
2427
|
async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
2323
|
-
const code = await publicClient.
|
|
2428
|
+
const code = await publicClient.getCode({ address: account });
|
|
2324
2429
|
if (!code) {
|
|
2325
2430
|
return false;
|
|
2326
2431
|
}
|
|
@@ -2337,36 +2442,7 @@ async function executeBatch(options, logger) {
|
|
|
2337
2442
|
if (!chain) {
|
|
2338
2443
|
throw new Error("Wallet client must have a chain");
|
|
2339
2444
|
}
|
|
2340
|
-
const
|
|
2341
|
-
[
|
|
2342
|
-
{
|
|
2343
|
-
type: "tuple[]",
|
|
2344
|
-
components: [
|
|
2345
|
-
{ name: "target", type: "address" },
|
|
2346
|
-
{ name: "value", type: "uint256" },
|
|
2347
|
-
{ name: "callData", type: "bytes" }
|
|
2348
|
-
]
|
|
2349
|
-
}
|
|
2350
|
-
],
|
|
2351
|
-
[executions]
|
|
2352
|
-
);
|
|
2353
|
-
const executeBatchMode = "0x0100000000000000000000000000000000000000000000000000000000000000";
|
|
2354
|
-
let executeBatchData;
|
|
2355
|
-
try {
|
|
2356
|
-
executeBatchData = (0, import_viem.encodeFunctionData)({
|
|
2357
|
-
abi: ERC7702Delegator_default,
|
|
2358
|
-
functionName: "execute",
|
|
2359
|
-
args: [executeBatchMode, encodedExecutions]
|
|
2360
|
-
});
|
|
2361
|
-
} catch {
|
|
2362
|
-
const functionSignature = "execute(bytes32,bytes)";
|
|
2363
|
-
const selector = (0, import_viem.keccak256)((0, import_viem.toBytes)(functionSignature)).slice(0, 10);
|
|
2364
|
-
const encodedParams = (0, import_viem.encodeAbiParameters)(
|
|
2365
|
-
[{ type: "bytes32" }, { type: "bytes" }],
|
|
2366
|
-
[executeBatchMode, encodedExecutions]
|
|
2367
|
-
);
|
|
2368
|
-
executeBatchData = (0, import_viem.concat)([selector, encodedParams]);
|
|
2369
|
-
}
|
|
2445
|
+
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2370
2446
|
const isDelegated2 = await checkERC7702Delegation(
|
|
2371
2447
|
publicClient,
|
|
2372
2448
|
account.address,
|
|
@@ -2520,12 +2596,23 @@ function stripHexPrefix(value) {
|
|
|
2520
2596
|
}
|
|
2521
2597
|
|
|
2522
2598
|
// src/client/common/utils/userapi.ts
|
|
2599
|
+
function isJsonObject(value) {
|
|
2600
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2601
|
+
}
|
|
2602
|
+
function readString(obj, key) {
|
|
2603
|
+
const v = obj[key];
|
|
2604
|
+
return typeof v === "string" ? v : void 0;
|
|
2605
|
+
}
|
|
2606
|
+
function readNumber(obj, key) {
|
|
2607
|
+
const v = obj[key];
|
|
2608
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
2609
|
+
}
|
|
2523
2610
|
var MAX_ADDRESS_COUNT = 5;
|
|
2524
2611
|
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
2525
2612
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
2526
2613
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
2527
2614
|
function getDefaultClientId() {
|
|
2528
|
-
const version = true ? "0.2.0-dev.
|
|
2615
|
+
const version = true ? "0.2.0-dev.3" : "0.0.0";
|
|
2529
2616
|
return `ecloud-sdk/v${version}`;
|
|
2530
2617
|
}
|
|
2531
2618
|
var UserApiClient = class {
|
|
@@ -2559,6 +2646,31 @@ var UserApiClient = class {
|
|
|
2559
2646
|
};
|
|
2560
2647
|
});
|
|
2561
2648
|
}
|
|
2649
|
+
/**
|
|
2650
|
+
* Get app details from UserAPI (includes releases and build/provenance info when available).
|
|
2651
|
+
*
|
|
2652
|
+
* Endpoint: GET /apps/:appAddress
|
|
2653
|
+
*/
|
|
2654
|
+
async getApp(appAddress) {
|
|
2655
|
+
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}`;
|
|
2656
|
+
const res = await this.makeAuthenticatedRequest(endpoint);
|
|
2657
|
+
const raw = await res.json();
|
|
2658
|
+
if (!isJsonObject(raw)) {
|
|
2659
|
+
throw new Error("Unexpected /apps/:id response: expected object");
|
|
2660
|
+
}
|
|
2661
|
+
const id = readString(raw, "id");
|
|
2662
|
+
if (!id) {
|
|
2663
|
+
throw new Error("Unexpected /apps/:id response: missing 'id'");
|
|
2664
|
+
}
|
|
2665
|
+
const releasesRaw = raw.releases;
|
|
2666
|
+
const releases = Array.isArray(releasesRaw) ? releasesRaw.map((r) => transformAppRelease(r)).filter((r) => !!r) : [];
|
|
2667
|
+
return {
|
|
2668
|
+
id,
|
|
2669
|
+
creator: readString(raw, "creator"),
|
|
2670
|
+
contractStatus: readString(raw, "contract_status") ?? readString(raw, "contractStatus"),
|
|
2671
|
+
releases
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2562
2674
|
/**
|
|
2563
2675
|
* Get available SKUs (instance types) from UserAPI
|
|
2564
2676
|
*/
|
|
@@ -2731,6 +2843,48 @@ Please check:
|
|
|
2731
2843
|
};
|
|
2732
2844
|
}
|
|
2733
2845
|
};
|
|
2846
|
+
function transformAppReleaseBuild(raw) {
|
|
2847
|
+
if (!isJsonObject(raw)) return void 0;
|
|
2848
|
+
const depsRaw = raw.dependencies;
|
|
2849
|
+
const deps = isJsonObject(depsRaw) ? Object.fromEntries(
|
|
2850
|
+
Object.entries(depsRaw).flatMap(([digest, depRaw]) => {
|
|
2851
|
+
const parsed = transformAppReleaseBuild(depRaw);
|
|
2852
|
+
return parsed ? [[digest, parsed]] : [];
|
|
2853
|
+
})
|
|
2854
|
+
) : void 0;
|
|
2855
|
+
return {
|
|
2856
|
+
buildId: readString(raw, "build_id") ?? readString(raw, "buildId"),
|
|
2857
|
+
billingAddress: readString(raw, "billing_address") ?? readString(raw, "billingAddress"),
|
|
2858
|
+
repoUrl: readString(raw, "repo_url") ?? readString(raw, "repoUrl"),
|
|
2859
|
+
gitRef: readString(raw, "git_ref") ?? readString(raw, "gitRef"),
|
|
2860
|
+
status: readString(raw, "status"),
|
|
2861
|
+
buildType: readString(raw, "build_type") ?? readString(raw, "buildType"),
|
|
2862
|
+
imageName: readString(raw, "image_name") ?? readString(raw, "imageName"),
|
|
2863
|
+
imageDigest: readString(raw, "image_digest") ?? readString(raw, "imageDigest"),
|
|
2864
|
+
imageUrl: readString(raw, "image_url") ?? readString(raw, "imageUrl"),
|
|
2865
|
+
provenanceJson: raw.provenance_json ?? raw.provenanceJson,
|
|
2866
|
+
provenanceSignature: readString(raw, "provenance_signature") ?? readString(raw, "provenanceSignature"),
|
|
2867
|
+
createdAt: readString(raw, "created_at") ?? readString(raw, "createdAt"),
|
|
2868
|
+
updatedAt: readString(raw, "updated_at") ?? readString(raw, "updatedAt"),
|
|
2869
|
+
errorMessage: readString(raw, "error_message") ?? readString(raw, "errorMessage"),
|
|
2870
|
+
dependencies: deps
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
function transformAppRelease(raw) {
|
|
2874
|
+
if (!isJsonObject(raw)) return void 0;
|
|
2875
|
+
return {
|
|
2876
|
+
appId: readString(raw, "appId") ?? readString(raw, "app_id"),
|
|
2877
|
+
rmsReleaseId: readString(raw, "rmsReleaseId") ?? readString(raw, "rms_release_id"),
|
|
2878
|
+
imageDigest: readString(raw, "imageDigest") ?? readString(raw, "image_digest"),
|
|
2879
|
+
registryUrl: readString(raw, "registryUrl") ?? readString(raw, "registry_url"),
|
|
2880
|
+
publicEnv: readString(raw, "publicEnv") ?? readString(raw, "public_env"),
|
|
2881
|
+
encryptedEnv: readString(raw, "encryptedEnv") ?? readString(raw, "encrypted_env"),
|
|
2882
|
+
upgradeByTime: readNumber(raw, "upgradeByTime") ?? readNumber(raw, "upgrade_by_time"),
|
|
2883
|
+
createdAt: readString(raw, "createdAt") ?? readString(raw, "created_at"),
|
|
2884
|
+
createdAtBlock: readString(raw, "createdAtBlock") ?? readString(raw, "created_at_block"),
|
|
2885
|
+
build: raw.build ? transformAppReleaseBuild(raw.build) : void 0
|
|
2886
|
+
};
|
|
2887
|
+
}
|
|
2734
2888
|
|
|
2735
2889
|
// src/client/common/utils/billing.ts
|
|
2736
2890
|
function isSubscriptionActive(status) {
|
|
@@ -4423,20 +4577,20 @@ async function prepareDeployBatch(options, logger) {
|
|
|
4423
4577
|
environmentConfig
|
|
4424
4578
|
};
|
|
4425
4579
|
}
|
|
4426
|
-
async function executeDeployBatch(
|
|
4580
|
+
async function executeDeployBatch(data, context, gas, logger) {
|
|
4427
4581
|
const pendingMessage = "Deploying new app...";
|
|
4428
4582
|
const txHash = await executeBatch(
|
|
4429
4583
|
{
|
|
4430
|
-
walletClient:
|
|
4431
|
-
publicClient:
|
|
4432
|
-
environmentConfig:
|
|
4433
|
-
executions:
|
|
4584
|
+
walletClient: context.walletClient,
|
|
4585
|
+
publicClient: context.publicClient,
|
|
4586
|
+
environmentConfig: context.environmentConfig,
|
|
4587
|
+
executions: data.executions,
|
|
4434
4588
|
pendingMessage,
|
|
4435
4589
|
gas
|
|
4436
4590
|
},
|
|
4437
4591
|
logger
|
|
4438
4592
|
);
|
|
4439
|
-
return { appId:
|
|
4593
|
+
return { appId: data.appId, txHash };
|
|
4440
4594
|
}
|
|
4441
4595
|
async function deployApp(options, logger) {
|
|
4442
4596
|
const prepared = await prepareDeployBatch(
|
|
@@ -4450,7 +4604,17 @@ async function deployApp(options, logger) {
|
|
|
4450
4604
|
},
|
|
4451
4605
|
logger
|
|
4452
4606
|
);
|
|
4453
|
-
|
|
4607
|
+
const data = {
|
|
4608
|
+
appId: prepared.appId,
|
|
4609
|
+
salt: prepared.salt,
|
|
4610
|
+
executions: prepared.executions
|
|
4611
|
+
};
|
|
4612
|
+
const context = {
|
|
4613
|
+
walletClient: prepared.walletClient,
|
|
4614
|
+
publicClient: prepared.publicClient,
|
|
4615
|
+
environmentConfig: prepared.environmentConfig
|
|
4616
|
+
};
|
|
4617
|
+
return executeDeployBatch(data, context, options.gas, logger);
|
|
4454
4618
|
}
|
|
4455
4619
|
async function prepareUpgradeBatch(options) {
|
|
4456
4620
|
const {
|
|
@@ -4546,14 +4710,14 @@ async function prepareUpgradeBatch(options) {
|
|
|
4546
4710
|
environmentConfig
|
|
4547
4711
|
};
|
|
4548
4712
|
}
|
|
4549
|
-
async function executeUpgradeBatch(
|
|
4550
|
-
const pendingMessage = `Upgrading app ${
|
|
4713
|
+
async function executeUpgradeBatch(data, context, gas, logger) {
|
|
4714
|
+
const pendingMessage = `Upgrading app ${data.appId}...`;
|
|
4551
4715
|
const txHash = await executeBatch(
|
|
4552
4716
|
{
|
|
4553
|
-
walletClient:
|
|
4554
|
-
publicClient:
|
|
4555
|
-
environmentConfig:
|
|
4556
|
-
executions:
|
|
4717
|
+
walletClient: context.walletClient,
|
|
4718
|
+
publicClient: context.publicClient,
|
|
4719
|
+
environmentConfig: context.environmentConfig,
|
|
4720
|
+
executions: data.executions,
|
|
4557
4721
|
pendingMessage,
|
|
4558
4722
|
gas
|
|
4559
4723
|
},
|
|
@@ -4571,7 +4735,16 @@ async function upgradeApp(options, logger) {
|
|
|
4571
4735
|
publicLogs: options.publicLogs,
|
|
4572
4736
|
needsPermissionChange: options.needsPermissionChange
|
|
4573
4737
|
});
|
|
4574
|
-
|
|
4738
|
+
const data = {
|
|
4739
|
+
appId: prepared.appId,
|
|
4740
|
+
executions: prepared.executions
|
|
4741
|
+
};
|
|
4742
|
+
const context = {
|
|
4743
|
+
walletClient: prepared.walletClient,
|
|
4744
|
+
publicClient: prepared.publicClient,
|
|
4745
|
+
environmentConfig: prepared.environmentConfig
|
|
4746
|
+
};
|
|
4747
|
+
return executeUpgradeBatch(data, context, options.gas, logger);
|
|
4575
4748
|
}
|
|
4576
4749
|
async function sendAndWaitForTransaction(options, logger) {
|
|
4577
4750
|
const {
|
|
@@ -5533,6 +5706,97 @@ async function withSDKTelemetry(options, action) {
|
|
|
5533
5706
|
}
|
|
5534
5707
|
|
|
5535
5708
|
// src/client/modules/compute/app/deploy.ts
|
|
5709
|
+
async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger) {
|
|
5710
|
+
return withSDKTelemetry(
|
|
5711
|
+
{
|
|
5712
|
+
functionName: "prepareDeployFromVerifiableBuild",
|
|
5713
|
+
skipTelemetry: options.skipTelemetry,
|
|
5714
|
+
properties: {
|
|
5715
|
+
environment: options.environment || "sepolia"
|
|
5716
|
+
}
|
|
5717
|
+
},
|
|
5718
|
+
async () => {
|
|
5719
|
+
if (!options.privateKey) throw new Error("privateKey is required for deployment");
|
|
5720
|
+
if (!options.imageRef) throw new Error("imageRef is required for deployment");
|
|
5721
|
+
if (!options.imageDigest) throw new Error("imageDigest is required for deployment");
|
|
5722
|
+
assertValidImageReference(options.imageRef);
|
|
5723
|
+
validateAppName(options.appName);
|
|
5724
|
+
validateLogVisibility(options.logVisibility);
|
|
5725
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(options.imageDigest)) {
|
|
5726
|
+
throw new Error(
|
|
5727
|
+
`imageDigest must be in format sha256:<64 hex>, got: ${options.imageDigest}`
|
|
5728
|
+
);
|
|
5729
|
+
}
|
|
5730
|
+
const { publicLogs } = validateLogVisibility(options.logVisibility);
|
|
5731
|
+
validateResourceUsageMonitoring(options.resourceUsageMonitoring);
|
|
5732
|
+
logger.debug("Performing preflight checks...");
|
|
5733
|
+
const preflightCtx = await doPreflightChecks(
|
|
5734
|
+
{
|
|
5735
|
+
privateKey: options.privateKey,
|
|
5736
|
+
rpcUrl: options.rpcUrl,
|
|
5737
|
+
environment: options.environment
|
|
5738
|
+
},
|
|
5739
|
+
logger
|
|
5740
|
+
);
|
|
5741
|
+
logger.debug("Checking quota availability...");
|
|
5742
|
+
await checkQuotaAvailable(preflightCtx);
|
|
5743
|
+
const salt = generateRandomSalt();
|
|
5744
|
+
logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
|
|
5745
|
+
logger.debug("Calculating app ID...");
|
|
5746
|
+
const appIDToBeDeployed = await calculateAppID(
|
|
5747
|
+
preflightCtx.privateKey,
|
|
5748
|
+
options.rpcUrl || preflightCtx.rpcUrl,
|
|
5749
|
+
preflightCtx.environmentConfig,
|
|
5750
|
+
salt
|
|
5751
|
+
);
|
|
5752
|
+
logger.info(``);
|
|
5753
|
+
logger.info(`App ID: ${appIDToBeDeployed}`);
|
|
5754
|
+
logger.info(``);
|
|
5755
|
+
const release = await createReleaseFromImageDigest(
|
|
5756
|
+
{
|
|
5757
|
+
imageRef: options.imageRef,
|
|
5758
|
+
imageDigest: options.imageDigest,
|
|
5759
|
+
envFilePath: options.envFilePath,
|
|
5760
|
+
instanceType: options.instanceType,
|
|
5761
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5762
|
+
appId: appIDToBeDeployed
|
|
5763
|
+
},
|
|
5764
|
+
logger
|
|
5765
|
+
);
|
|
5766
|
+
logger.debug("Preparing deploy batch...");
|
|
5767
|
+
const batch = await prepareDeployBatch(
|
|
5768
|
+
{
|
|
5769
|
+
privateKey: preflightCtx.privateKey,
|
|
5770
|
+
rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
|
|
5771
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5772
|
+
salt,
|
|
5773
|
+
release,
|
|
5774
|
+
publicLogs
|
|
5775
|
+
},
|
|
5776
|
+
logger
|
|
5777
|
+
);
|
|
5778
|
+
logger.debug("Estimating gas...");
|
|
5779
|
+
const gasEstimate = await estimateBatchGas({
|
|
5780
|
+
publicClient: batch.publicClient,
|
|
5781
|
+
account: batch.walletClient.account.address,
|
|
5782
|
+
executions: batch.executions
|
|
5783
|
+
});
|
|
5784
|
+
const data = {
|
|
5785
|
+
appId: batch.appId,
|
|
5786
|
+
salt: batch.salt,
|
|
5787
|
+
executions: batch.executions
|
|
5788
|
+
};
|
|
5789
|
+
return {
|
|
5790
|
+
prepared: {
|
|
5791
|
+
data,
|
|
5792
|
+
appName: options.appName,
|
|
5793
|
+
imageRef: options.imageRef
|
|
5794
|
+
},
|
|
5795
|
+
gasEstimate
|
|
5796
|
+
};
|
|
5797
|
+
}
|
|
5798
|
+
);
|
|
5799
|
+
}
|
|
5536
5800
|
function validateDeployOptions(options) {
|
|
5537
5801
|
if (!options.privateKey) {
|
|
5538
5802
|
throw new Error("privateKey is required for deployment");
|
|
@@ -5753,26 +6017,27 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
5753
6017
|
logger.debug("Estimating gas...");
|
|
5754
6018
|
const gasEstimate = await estimateBatchGas({
|
|
5755
6019
|
publicClient: batch.publicClient,
|
|
5756
|
-
|
|
6020
|
+
account: batch.walletClient.account.address,
|
|
5757
6021
|
executions: batch.executions
|
|
5758
6022
|
});
|
|
6023
|
+
const data = {
|
|
6024
|
+
appId: batch.appId,
|
|
6025
|
+
salt: batch.salt,
|
|
6026
|
+
executions: batch.executions
|
|
6027
|
+
};
|
|
5759
6028
|
return {
|
|
5760
6029
|
prepared: {
|
|
5761
|
-
|
|
6030
|
+
data,
|
|
5762
6031
|
appName,
|
|
5763
|
-
imageRef: finalImageRef
|
|
5764
|
-
preflightCtx: {
|
|
5765
|
-
privateKey: preflightCtx.privateKey,
|
|
5766
|
-
rpcUrl: preflightCtx.rpcUrl,
|
|
5767
|
-
environmentConfig: preflightCtx.environmentConfig
|
|
5768
|
-
}
|
|
6032
|
+
imageRef: finalImageRef
|
|
5769
6033
|
},
|
|
5770
6034
|
gasEstimate
|
|
5771
6035
|
};
|
|
5772
6036
|
}
|
|
5773
6037
|
);
|
|
5774
6038
|
}
|
|
5775
|
-
async function executeDeploy(
|
|
6039
|
+
async function executeDeploy(options) {
|
|
6040
|
+
const { prepared, context, gas, logger = defaultLogger, skipTelemetry } = options;
|
|
5776
6041
|
return withSDKTelemetry(
|
|
5777
6042
|
{
|
|
5778
6043
|
functionName: "executeDeploy",
|
|
@@ -5780,7 +6045,7 @@ async function executeDeploy(prepared, gas, logger = defaultLogger, skipTelemetr
|
|
|
5780
6045
|
},
|
|
5781
6046
|
async () => {
|
|
5782
6047
|
logger.info("Deploying on-chain...");
|
|
5783
|
-
const { appId, txHash } = await executeDeployBatch(prepared.
|
|
6048
|
+
const { appId, txHash } = await executeDeployBatch(prepared.data, context, gas, logger);
|
|
5784
6049
|
return {
|
|
5785
6050
|
appId,
|
|
5786
6051
|
txHash,
|
|
@@ -5842,6 +6107,81 @@ async function checkAppLogPermission(preflightCtx, appAddress, logger) {
|
|
|
5842
6107
|
}
|
|
5843
6108
|
|
|
5844
6109
|
// src/client/modules/compute/app/upgrade.ts
|
|
6110
|
+
async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger) {
|
|
6111
|
+
return withSDKTelemetry(
|
|
6112
|
+
{
|
|
6113
|
+
functionName: "prepareUpgradeFromVerifiableBuild",
|
|
6114
|
+
skipTelemetry: options.skipTelemetry,
|
|
6115
|
+
properties: {
|
|
6116
|
+
environment: options.environment || "sepolia"
|
|
6117
|
+
}
|
|
6118
|
+
},
|
|
6119
|
+
async () => {
|
|
6120
|
+
logger.debug("Performing preflight checks...");
|
|
6121
|
+
const preflightCtx = await doPreflightChecks(
|
|
6122
|
+
{
|
|
6123
|
+
privateKey: options.privateKey,
|
|
6124
|
+
rpcUrl: options.rpcUrl,
|
|
6125
|
+
environment: options.environment
|
|
6126
|
+
},
|
|
6127
|
+
logger
|
|
6128
|
+
);
|
|
6129
|
+
const appID = validateUpgradeOptions(options);
|
|
6130
|
+
assertValidImageReference(options.imageRef);
|
|
6131
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(options.imageDigest)) {
|
|
6132
|
+
throw new Error(
|
|
6133
|
+
`imageDigest must be in format sha256:<64 hex>, got: ${options.imageDigest}`
|
|
6134
|
+
);
|
|
6135
|
+
}
|
|
6136
|
+
const { publicLogs } = validateLogVisibility(options.logVisibility);
|
|
6137
|
+
validateResourceUsageMonitoring(options.resourceUsageMonitoring);
|
|
6138
|
+
const envFilePath = options.envFilePath || "";
|
|
6139
|
+
logger.info("Preparing release (verifiable build, no local layering)...");
|
|
6140
|
+
const release = await createReleaseFromImageDigest(
|
|
6141
|
+
{
|
|
6142
|
+
imageRef: options.imageRef,
|
|
6143
|
+
imageDigest: options.imageDigest,
|
|
6144
|
+
envFilePath,
|
|
6145
|
+
instanceType: options.instanceType,
|
|
6146
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
6147
|
+
appId: appID
|
|
6148
|
+
},
|
|
6149
|
+
logger
|
|
6150
|
+
);
|
|
6151
|
+
logger.debug("Checking current log permission state...");
|
|
6152
|
+
const currentlyPublic = await checkAppLogPermission(preflightCtx, appID, logger);
|
|
6153
|
+
const needsPermissionChange = currentlyPublic !== publicLogs;
|
|
6154
|
+
logger.debug("Preparing upgrade batch...");
|
|
6155
|
+
const batch = await prepareUpgradeBatch({
|
|
6156
|
+
privateKey: preflightCtx.privateKey,
|
|
6157
|
+
rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
|
|
6158
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
6159
|
+
appId: appID,
|
|
6160
|
+
release,
|
|
6161
|
+
publicLogs,
|
|
6162
|
+
needsPermissionChange
|
|
6163
|
+
});
|
|
6164
|
+
logger.debug("Estimating gas...");
|
|
6165
|
+
const gasEstimate = await estimateBatchGas({
|
|
6166
|
+
publicClient: batch.publicClient,
|
|
6167
|
+
account: batch.walletClient.account.address,
|
|
6168
|
+
executions: batch.executions
|
|
6169
|
+
});
|
|
6170
|
+
const data = {
|
|
6171
|
+
appId: batch.appId,
|
|
6172
|
+
executions: batch.executions
|
|
6173
|
+
};
|
|
6174
|
+
return {
|
|
6175
|
+
prepared: {
|
|
6176
|
+
data,
|
|
6177
|
+
appId: appID,
|
|
6178
|
+
imageRef: options.imageRef
|
|
6179
|
+
},
|
|
6180
|
+
gasEstimate
|
|
6181
|
+
};
|
|
6182
|
+
}
|
|
6183
|
+
);
|
|
6184
|
+
}
|
|
5845
6185
|
function validateUpgradeOptions(options) {
|
|
5846
6186
|
if (!options.privateKey) {
|
|
5847
6187
|
throw new Error("privateKey is required for upgrade");
|
|
@@ -6004,26 +6344,26 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
6004
6344
|
logger.debug("Estimating gas...");
|
|
6005
6345
|
const gasEstimate = await estimateBatchGas({
|
|
6006
6346
|
publicClient: batch.publicClient,
|
|
6007
|
-
|
|
6347
|
+
account: batch.walletClient.account.address,
|
|
6008
6348
|
executions: batch.executions
|
|
6009
6349
|
});
|
|
6350
|
+
const data = {
|
|
6351
|
+
appId: batch.appId,
|
|
6352
|
+
executions: batch.executions
|
|
6353
|
+
};
|
|
6010
6354
|
return {
|
|
6011
6355
|
prepared: {
|
|
6012
|
-
|
|
6356
|
+
data,
|
|
6013
6357
|
appId: appID,
|
|
6014
|
-
imageRef: finalImageRef
|
|
6015
|
-
preflightCtx: {
|
|
6016
|
-
privateKey: preflightCtx.privateKey,
|
|
6017
|
-
rpcUrl: preflightCtx.rpcUrl,
|
|
6018
|
-
environmentConfig: preflightCtx.environmentConfig
|
|
6019
|
-
}
|
|
6358
|
+
imageRef: finalImageRef
|
|
6020
6359
|
},
|
|
6021
6360
|
gasEstimate
|
|
6022
6361
|
};
|
|
6023
6362
|
}
|
|
6024
6363
|
);
|
|
6025
6364
|
}
|
|
6026
|
-
async function executeUpgrade(
|
|
6365
|
+
async function executeUpgrade(options) {
|
|
6366
|
+
const { prepared, context, gas, logger = defaultLogger, skipTelemetry } = options;
|
|
6027
6367
|
return withSDKTelemetry(
|
|
6028
6368
|
{
|
|
6029
6369
|
functionName: "executeUpgrade",
|
|
@@ -6031,7 +6371,7 @@ async function executeUpgrade(prepared, gas, logger = defaultLogger, skipTelemet
|
|
|
6031
6371
|
},
|
|
6032
6372
|
async () => {
|
|
6033
6373
|
logger.info("Upgrading on-chain...");
|
|
6034
|
-
const txHash = await executeUpgradeBatch(prepared.
|
|
6374
|
+
const txHash = await executeUpgradeBatch(prepared.data, context, gas, logger);
|
|
6035
6375
|
return {
|
|
6036
6376
|
appId: prepared.appId,
|
|
6037
6377
|
imageRef: prepared.imageRef,
|
|
@@ -6162,8 +6502,8 @@ var path5 = __toESM(require("path"), 1);
|
|
|
6162
6502
|
var os3 = __toESM(require("os"), 1);
|
|
6163
6503
|
var import_child_process2 = require("child_process");
|
|
6164
6504
|
var import_util4 = require("util");
|
|
6165
|
-
var
|
|
6166
|
-
var
|
|
6505
|
+
var execAsync = (0, import_util4.promisify)(import_child_process2.exec);
|
|
6506
|
+
var execFileAsync3 = (0, import_util4.promisify)(import_child_process2.execFile);
|
|
6167
6507
|
async function fetchTemplate(repoURL, ref, targetDir, config, logger) {
|
|
6168
6508
|
if (!repoURL) {
|
|
6169
6509
|
throw new Error("repoURL is required");
|
|
@@ -6172,13 +6512,13 @@ async function fetchTemplate(repoURL, ref, targetDir, config, logger) {
|
|
|
6172
6512
|
Cloning repo: ${repoURL} \u2192 ${targetDir}
|
|
6173
6513
|
`);
|
|
6174
6514
|
try {
|
|
6175
|
-
await
|
|
6515
|
+
await execAsync(`git clone --no-checkout --progress ${repoURL} ${targetDir}`, {
|
|
6176
6516
|
maxBuffer: 10 * 1024 * 1024
|
|
6177
6517
|
});
|
|
6178
|
-
await
|
|
6518
|
+
await execFileAsync3("git", ["-C", targetDir, "checkout", "--quiet", ref], {
|
|
6179
6519
|
maxBuffer: 10 * 1024 * 1024
|
|
6180
6520
|
});
|
|
6181
|
-
await
|
|
6521
|
+
await execFileAsync3(
|
|
6182
6522
|
"git",
|
|
6183
6523
|
["-C", targetDir, "submodule", "update", "--init", "--recursive", "--progress"],
|
|
6184
6524
|
{ maxBuffer: 10 * 1024 * 1024 }
|
|
@@ -6223,14 +6563,14 @@ Cloning template: ${repoURL} \u2192 extracting ${subPath}
|
|
|
6223
6563
|
}
|
|
6224
6564
|
async function cloneSparse(repoURL, ref, subPath, tempDir) {
|
|
6225
6565
|
try {
|
|
6226
|
-
await
|
|
6227
|
-
await
|
|
6228
|
-
await
|
|
6566
|
+
await execFileAsync3("git", ["init", tempDir]);
|
|
6567
|
+
await execFileAsync3("git", ["-C", tempDir, "remote", "add", "origin", repoURL]);
|
|
6568
|
+
await execFileAsync3("git", ["-C", tempDir, "config", "core.sparseCheckout", "true"]);
|
|
6229
6569
|
const sparseCheckoutPath = path5.join(tempDir, ".git/info/sparse-checkout");
|
|
6230
6570
|
fs5.writeFileSync(sparseCheckoutPath, `${subPath}
|
|
6231
6571
|
`);
|
|
6232
|
-
await
|
|
6233
|
-
await
|
|
6572
|
+
await execFileAsync3("git", ["-C", tempDir, "fetch", "origin", ref]);
|
|
6573
|
+
await execFileAsync3("git", ["-C", tempDir, "checkout", ref]);
|
|
6234
6574
|
} catch (error) {
|
|
6235
6575
|
throw new Error(`Failed to clone sparse repository: ${error.message}`);
|
|
6236
6576
|
}
|
|
@@ -6805,6 +7145,187 @@ function createAppModule(ctx) {
|
|
|
6805
7145
|
imageRef: result.imageRef
|
|
6806
7146
|
};
|
|
6807
7147
|
},
|
|
7148
|
+
// Granular deploy control
|
|
7149
|
+
async prepareDeploy(opts) {
|
|
7150
|
+
return prepareDeploy(
|
|
7151
|
+
{
|
|
7152
|
+
privateKey,
|
|
7153
|
+
rpcUrl: ctx.rpcUrl,
|
|
7154
|
+
environment: ctx.environment,
|
|
7155
|
+
appName: opts.name,
|
|
7156
|
+
instanceType: opts.instanceType,
|
|
7157
|
+
dockerfilePath: opts.dockerfile,
|
|
7158
|
+
envFilePath: opts.envFile,
|
|
7159
|
+
imageRef: opts.imageRef,
|
|
7160
|
+
logVisibility: opts.logVisibility,
|
|
7161
|
+
resourceUsageMonitoring: opts.resourceUsageMonitoring,
|
|
7162
|
+
skipTelemetry
|
|
7163
|
+
},
|
|
7164
|
+
logger
|
|
7165
|
+
);
|
|
7166
|
+
},
|
|
7167
|
+
async prepareDeployFromVerifiableBuild(opts) {
|
|
7168
|
+
return prepareDeployFromVerifiableBuild(
|
|
7169
|
+
{
|
|
7170
|
+
privateKey,
|
|
7171
|
+
rpcUrl: ctx.rpcUrl,
|
|
7172
|
+
environment: ctx.environment,
|
|
7173
|
+
appName: opts.name,
|
|
7174
|
+
instanceType: opts.instanceType,
|
|
7175
|
+
envFilePath: opts.envFile,
|
|
7176
|
+
imageRef: opts.imageRef,
|
|
7177
|
+
imageDigest: opts.imageDigest,
|
|
7178
|
+
logVisibility: opts.logVisibility,
|
|
7179
|
+
resourceUsageMonitoring: opts.resourceUsageMonitoring,
|
|
7180
|
+
skipTelemetry
|
|
7181
|
+
},
|
|
7182
|
+
logger
|
|
7183
|
+
);
|
|
7184
|
+
},
|
|
7185
|
+
async executeDeploy(prepared, gas) {
|
|
7186
|
+
const account = (0, import_accounts5.privateKeyToAccount)(privateKey);
|
|
7187
|
+
const chain = getChainFromID(environment.chainID);
|
|
7188
|
+
const publicClient = (0, import_viem9.createPublicClient)({
|
|
7189
|
+
chain,
|
|
7190
|
+
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
7191
|
+
});
|
|
7192
|
+
const walletClient = (0, import_viem9.createWalletClient)({
|
|
7193
|
+
account,
|
|
7194
|
+
chain,
|
|
7195
|
+
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
7196
|
+
});
|
|
7197
|
+
const result = await executeDeploy({
|
|
7198
|
+
prepared,
|
|
7199
|
+
context: {
|
|
7200
|
+
walletClient,
|
|
7201
|
+
publicClient,
|
|
7202
|
+
environmentConfig: environment
|
|
7203
|
+
},
|
|
7204
|
+
gas,
|
|
7205
|
+
logger,
|
|
7206
|
+
skipTelemetry
|
|
7207
|
+
});
|
|
7208
|
+
return {
|
|
7209
|
+
appId: result.appId,
|
|
7210
|
+
txHash: result.txHash,
|
|
7211
|
+
appName: result.appName,
|
|
7212
|
+
imageRef: result.imageRef
|
|
7213
|
+
};
|
|
7214
|
+
},
|
|
7215
|
+
async watchDeployment(appId) {
|
|
7216
|
+
return watchDeployment(
|
|
7217
|
+
appId,
|
|
7218
|
+
privateKey,
|
|
7219
|
+
ctx.rpcUrl,
|
|
7220
|
+
ctx.environment,
|
|
7221
|
+
logger,
|
|
7222
|
+
ctx.clientId,
|
|
7223
|
+
skipTelemetry
|
|
7224
|
+
);
|
|
7225
|
+
},
|
|
7226
|
+
// Granular upgrade control
|
|
7227
|
+
async prepareUpgrade(appId, opts) {
|
|
7228
|
+
return prepareUpgrade(
|
|
7229
|
+
{
|
|
7230
|
+
appId,
|
|
7231
|
+
privateKey,
|
|
7232
|
+
rpcUrl: ctx.rpcUrl,
|
|
7233
|
+
environment: ctx.environment,
|
|
7234
|
+
instanceType: opts.instanceType,
|
|
7235
|
+
dockerfilePath: opts.dockerfile,
|
|
7236
|
+
envFilePath: opts.envFile,
|
|
7237
|
+
imageRef: opts.imageRef,
|
|
7238
|
+
logVisibility: opts.logVisibility,
|
|
7239
|
+
resourceUsageMonitoring: opts.resourceUsageMonitoring,
|
|
7240
|
+
skipTelemetry
|
|
7241
|
+
},
|
|
7242
|
+
logger
|
|
7243
|
+
);
|
|
7244
|
+
},
|
|
7245
|
+
async prepareUpgradeFromVerifiableBuild(appId, opts) {
|
|
7246
|
+
return prepareUpgradeFromVerifiableBuild(
|
|
7247
|
+
{
|
|
7248
|
+
appId,
|
|
7249
|
+
privateKey,
|
|
7250
|
+
rpcUrl: ctx.rpcUrl,
|
|
7251
|
+
environment: ctx.environment,
|
|
7252
|
+
instanceType: opts.instanceType,
|
|
7253
|
+
envFilePath: opts.envFile,
|
|
7254
|
+
imageRef: opts.imageRef,
|
|
7255
|
+
imageDigest: opts.imageDigest,
|
|
7256
|
+
logVisibility: opts.logVisibility,
|
|
7257
|
+
resourceUsageMonitoring: opts.resourceUsageMonitoring,
|
|
7258
|
+
skipTelemetry
|
|
7259
|
+
},
|
|
7260
|
+
logger
|
|
7261
|
+
);
|
|
7262
|
+
},
|
|
7263
|
+
async executeUpgrade(prepared, gas) {
|
|
7264
|
+
const account = (0, import_accounts5.privateKeyToAccount)(privateKey);
|
|
7265
|
+
const chain = getChainFromID(environment.chainID);
|
|
7266
|
+
const publicClient = (0, import_viem9.createPublicClient)({
|
|
7267
|
+
chain,
|
|
7268
|
+
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
7269
|
+
});
|
|
7270
|
+
const walletClient = (0, import_viem9.createWalletClient)({
|
|
7271
|
+
account,
|
|
7272
|
+
chain,
|
|
7273
|
+
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
7274
|
+
});
|
|
7275
|
+
const result = await executeUpgrade({
|
|
7276
|
+
prepared,
|
|
7277
|
+
context: {
|
|
7278
|
+
walletClient,
|
|
7279
|
+
publicClient,
|
|
7280
|
+
environmentConfig: environment
|
|
7281
|
+
},
|
|
7282
|
+
gas,
|
|
7283
|
+
logger,
|
|
7284
|
+
skipTelemetry
|
|
7285
|
+
});
|
|
7286
|
+
return {
|
|
7287
|
+
appId: result.appId,
|
|
7288
|
+
txHash: result.txHash,
|
|
7289
|
+
imageRef: result.imageRef
|
|
7290
|
+
};
|
|
7291
|
+
},
|
|
7292
|
+
async watchUpgrade(appId) {
|
|
7293
|
+
return watchUpgrade(
|
|
7294
|
+
appId,
|
|
7295
|
+
privateKey,
|
|
7296
|
+
ctx.rpcUrl,
|
|
7297
|
+
ctx.environment,
|
|
7298
|
+
logger,
|
|
7299
|
+
ctx.clientId,
|
|
7300
|
+
skipTelemetry
|
|
7301
|
+
);
|
|
7302
|
+
},
|
|
7303
|
+
// Profile management
|
|
7304
|
+
async setProfile(appId, profile) {
|
|
7305
|
+
return withSDKTelemetry(
|
|
7306
|
+
{
|
|
7307
|
+
functionName: "setProfile",
|
|
7308
|
+
skipTelemetry,
|
|
7309
|
+
properties: { environment: ctx.environment }
|
|
7310
|
+
},
|
|
7311
|
+
async () => {
|
|
7312
|
+
const userApiClient = new UserApiClient(
|
|
7313
|
+
environment,
|
|
7314
|
+
privateKey,
|
|
7315
|
+
ctx.rpcUrl,
|
|
7316
|
+
ctx.clientId
|
|
7317
|
+
);
|
|
7318
|
+
return userApiClient.uploadAppProfile(
|
|
7319
|
+
appId,
|
|
7320
|
+
profile.name,
|
|
7321
|
+
profile.website,
|
|
7322
|
+
profile.description,
|
|
7323
|
+
profile.xURL,
|
|
7324
|
+
profile.imagePath
|
|
7325
|
+
);
|
|
7326
|
+
}
|
|
7327
|
+
);
|
|
7328
|
+
},
|
|
6808
7329
|
async logs(opts) {
|
|
6809
7330
|
return logs(
|
|
6810
7331
|
{
|
|
@@ -6955,10 +7476,10 @@ function createComputeModule(config) {
|
|
|
6955
7476
|
|
|
6956
7477
|
// src/client/common/utils/billingapi.ts
|
|
6957
7478
|
var import_axios2 = __toESM(require("axios"), 1);
|
|
6958
|
-
var
|
|
7479
|
+
var import_accounts6 = require("viem/accounts");
|
|
6959
7480
|
var BillingApiClient = class {
|
|
6960
7481
|
constructor(config, privateKey) {
|
|
6961
|
-
this.account = (0,
|
|
7482
|
+
this.account = (0, import_accounts6.privateKeyToAccount)(privateKey);
|
|
6962
7483
|
this.config = config;
|
|
6963
7484
|
}
|
|
6964
7485
|
async createSubscription(productId = "compute") {
|
|
@@ -7028,7 +7549,7 @@ Please check:
|
|
|
7028
7549
|
|
|
7029
7550
|
// src/client/common/auth/keyring.ts
|
|
7030
7551
|
var import_keyring = require("@napi-rs/keyring");
|
|
7031
|
-
var
|
|
7552
|
+
var import_accounts7 = require("viem/accounts");
|
|
7032
7553
|
var SERVICE_NAME = "ecloud";
|
|
7033
7554
|
var ACCOUNT_NAME = "key";
|
|
7034
7555
|
var EIGENX_SERVICE_NAME = "eigenx-cli";
|
|
@@ -7173,7 +7694,7 @@ function validatePrivateKey2(privateKey) {
|
|
|
7173
7694
|
}
|
|
7174
7695
|
function getAddressFromPrivateKey(privateKey) {
|
|
7175
7696
|
const normalized = normalizePrivateKey(privateKey);
|
|
7176
|
-
return (0,
|
|
7697
|
+
return (0, import_accounts7.privateKeyToAddress)(normalized);
|
|
7177
7698
|
}
|
|
7178
7699
|
function decodeGoKeyringValue(rawValue) {
|
|
7179
7700
|
if (rawValue.startsWith(GO_KEYRING_BASE64_PREFIX)) {
|
|
@@ -7255,10 +7776,10 @@ async function requirePrivateKey(options) {
|
|
|
7255
7776
|
}
|
|
7256
7777
|
|
|
7257
7778
|
// src/client/common/auth/generate.ts
|
|
7258
|
-
var
|
|
7779
|
+
var import_accounts8 = require("viem/accounts");
|
|
7259
7780
|
function generateNewPrivateKey() {
|
|
7260
|
-
const privateKey = (0,
|
|
7261
|
-
const address = (0,
|
|
7781
|
+
const privateKey = (0, import_accounts8.generatePrivateKey)();
|
|
7782
|
+
const address = (0, import_accounts8.privateKeyToAddress)(privateKey);
|
|
7262
7783
|
return {
|
|
7263
7784
|
privateKey,
|
|
7264
7785
|
address
|
|
@@ -7360,6 +7881,360 @@ function createBillingModule(config) {
|
|
|
7360
7881
|
};
|
|
7361
7882
|
}
|
|
7362
7883
|
|
|
7884
|
+
// src/client/common/utils/buildapi.ts
|
|
7885
|
+
var import_axios3 = __toESM(require("axios"), 1);
|
|
7886
|
+
var import_accounts9 = require("viem/accounts");
|
|
7887
|
+
var BuildApiClient = class {
|
|
7888
|
+
constructor(options) {
|
|
7889
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
7890
|
+
this.clientId = options.clientId;
|
|
7891
|
+
if (options.privateKey) {
|
|
7892
|
+
this.account = (0, import_accounts9.privateKeyToAccount)(options.privateKey);
|
|
7893
|
+
}
|
|
7894
|
+
}
|
|
7895
|
+
async submitBuild(payload) {
|
|
7896
|
+
return this.authenticatedJsonRequest("/builds", "POST", payload);
|
|
7897
|
+
}
|
|
7898
|
+
async getBuild(buildId) {
|
|
7899
|
+
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
7900
|
+
}
|
|
7901
|
+
async getBuildByDigest(digest) {
|
|
7902
|
+
return this.publicJsonRequest(`/builds/image/${encodeURIComponent(digest)}`);
|
|
7903
|
+
}
|
|
7904
|
+
async verify(identifier) {
|
|
7905
|
+
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7906
|
+
}
|
|
7907
|
+
async getLogs(buildId) {
|
|
7908
|
+
return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7909
|
+
}
|
|
7910
|
+
async listBuilds(params) {
|
|
7911
|
+
const res = await (0, import_axios3.default)({
|
|
7912
|
+
url: `${this.baseUrl}/builds`,
|
|
7913
|
+
method: "GET",
|
|
7914
|
+
params,
|
|
7915
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7916
|
+
timeout: 6e4,
|
|
7917
|
+
validateStatus: () => true
|
|
7918
|
+
});
|
|
7919
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7920
|
+
return res.data;
|
|
7921
|
+
}
|
|
7922
|
+
async publicJsonRequest(path8) {
|
|
7923
|
+
const res = await (0, import_axios3.default)({
|
|
7924
|
+
url: `${this.baseUrl}${path8}`,
|
|
7925
|
+
method: "GET",
|
|
7926
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7927
|
+
timeout: 6e4,
|
|
7928
|
+
validateStatus: () => true
|
|
7929
|
+
});
|
|
7930
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7931
|
+
return res.data;
|
|
7932
|
+
}
|
|
7933
|
+
async authenticatedJsonRequest(path8, method, body) {
|
|
7934
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
7935
|
+
const headers = {
|
|
7936
|
+
"Content-Type": "application/json"
|
|
7937
|
+
};
|
|
7938
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7939
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
7940
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
7941
|
+
account: this.account,
|
|
7942
|
+
product: "compute",
|
|
7943
|
+
expiry
|
|
7944
|
+
});
|
|
7945
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
7946
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7947
|
+
headers["X-Account"] = this.account.address;
|
|
7948
|
+
const res = await (0, import_axios3.default)({
|
|
7949
|
+
url: `${this.baseUrl}${path8}`,
|
|
7950
|
+
method,
|
|
7951
|
+
headers,
|
|
7952
|
+
data: body,
|
|
7953
|
+
timeout: 6e4,
|
|
7954
|
+
validateStatus: () => true
|
|
7955
|
+
});
|
|
7956
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7957
|
+
return res.data;
|
|
7958
|
+
}
|
|
7959
|
+
async authenticatedTextRequest(path8) {
|
|
7960
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
7961
|
+
const headers = {};
|
|
7962
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7963
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
7964
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
7965
|
+
account: this.account,
|
|
7966
|
+
product: "compute",
|
|
7967
|
+
expiry
|
|
7968
|
+
});
|
|
7969
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
7970
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7971
|
+
headers["X-Account"] = this.account.address;
|
|
7972
|
+
const res = await (0, import_axios3.default)({
|
|
7973
|
+
url: `${this.baseUrl}${path8}`,
|
|
7974
|
+
method: "GET",
|
|
7975
|
+
headers,
|
|
7976
|
+
timeout: 6e4,
|
|
7977
|
+
responseType: "text",
|
|
7978
|
+
validateStatus: () => true
|
|
7979
|
+
});
|
|
7980
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7981
|
+
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
7982
|
+
}
|
|
7983
|
+
};
|
|
7984
|
+
function buildApiHttpError(res) {
|
|
7985
|
+
const status = res.status;
|
|
7986
|
+
const body = typeof res.data === "string" ? res.data : res.data ? JSON.stringify(res.data) : "";
|
|
7987
|
+
const url = res.config?.url ? ` ${res.config.url}` : "";
|
|
7988
|
+
return new Error(`BuildAPI request failed: ${status}${url} - ${body || "Unknown error"}`);
|
|
7989
|
+
}
|
|
7990
|
+
|
|
7991
|
+
// src/client/modules/build/types.ts
|
|
7992
|
+
var BUILD_STATUS = {
|
|
7993
|
+
BUILDING: "building",
|
|
7994
|
+
SUCCESS: "success",
|
|
7995
|
+
FAILED: "failed"
|
|
7996
|
+
};
|
|
7997
|
+
|
|
7998
|
+
// src/client/modules/build/errors.ts
|
|
7999
|
+
var BuildError = class extends Error {
|
|
8000
|
+
constructor(message) {
|
|
8001
|
+
super(message);
|
|
8002
|
+
this.name = "BuildError";
|
|
8003
|
+
}
|
|
8004
|
+
};
|
|
8005
|
+
var AuthRequiredError = class extends BuildError {
|
|
8006
|
+
constructor(message = "Authentication required") {
|
|
8007
|
+
super(message);
|
|
8008
|
+
this.name = "AuthRequiredError";
|
|
8009
|
+
}
|
|
8010
|
+
};
|
|
8011
|
+
var BuildFailedError = class extends BuildError {
|
|
8012
|
+
constructor(message, buildId) {
|
|
8013
|
+
super(message);
|
|
8014
|
+
this.buildId = buildId;
|
|
8015
|
+
this.name = "BuildFailedError";
|
|
8016
|
+
}
|
|
8017
|
+
};
|
|
8018
|
+
var ConflictError = class extends BuildError {
|
|
8019
|
+
constructor(message = "Build already in progress") {
|
|
8020
|
+
super(message);
|
|
8021
|
+
this.name = "ConflictError";
|
|
8022
|
+
}
|
|
8023
|
+
};
|
|
8024
|
+
var NotFoundError = class extends BuildError {
|
|
8025
|
+
constructor(message = "Build not found") {
|
|
8026
|
+
super(message);
|
|
8027
|
+
this.name = "NotFoundError";
|
|
8028
|
+
}
|
|
8029
|
+
};
|
|
8030
|
+
var ForbiddenError = class extends BuildError {
|
|
8031
|
+
constructor(message = "Permission denied") {
|
|
8032
|
+
super(message);
|
|
8033
|
+
this.name = "ForbiddenError";
|
|
8034
|
+
}
|
|
8035
|
+
};
|
|
8036
|
+
var TimeoutError = class extends BuildError {
|
|
8037
|
+
constructor(message = "Operation timed out") {
|
|
8038
|
+
super(message);
|
|
8039
|
+
this.name = "TimeoutError";
|
|
8040
|
+
}
|
|
8041
|
+
};
|
|
8042
|
+
var BadRequestError = class extends BuildError {
|
|
8043
|
+
constructor(message = "Bad request") {
|
|
8044
|
+
super(message);
|
|
8045
|
+
this.name = "BadRequestError";
|
|
8046
|
+
}
|
|
8047
|
+
};
|
|
8048
|
+
|
|
8049
|
+
// src/client/modules/build/index.ts
|
|
8050
|
+
var DEFAULT_POLL_INTERVAL = 2e3;
|
|
8051
|
+
var DEFAULT_TIMEOUT = 30 * 60 * 1e3;
|
|
8052
|
+
function createBuildModule(config) {
|
|
8053
|
+
const { verbose = false, skipTelemetry = false } = config;
|
|
8054
|
+
const logger = getLogger(verbose);
|
|
8055
|
+
const environment = config.environment || "sepolia";
|
|
8056
|
+
const environmentConfig = getEnvironmentConfig(environment);
|
|
8057
|
+
const api = new BuildApiClient({
|
|
8058
|
+
baseUrl: environmentConfig.userApiServerURL,
|
|
8059
|
+
privateKey: config.privateKey ? addHexPrefix(config.privateKey) : void 0,
|
|
8060
|
+
clientId: config.clientId
|
|
8061
|
+
});
|
|
8062
|
+
return {
|
|
8063
|
+
async submit(request) {
|
|
8064
|
+
return withSDKTelemetry(
|
|
8065
|
+
{
|
|
8066
|
+
functionName: "build.submit",
|
|
8067
|
+
skipTelemetry,
|
|
8068
|
+
properties: { environment, repoUrl: request.repoUrl }
|
|
8069
|
+
},
|
|
8070
|
+
async () => {
|
|
8071
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for submit()");
|
|
8072
|
+
const data = await api.submitBuild({
|
|
8073
|
+
repo_url: request.repoUrl,
|
|
8074
|
+
git_ref: request.gitRef,
|
|
8075
|
+
dockerfile_path: request.dockerfilePath ?? "Dockerfile",
|
|
8076
|
+
caddyfile_path: request.caddyfilePath,
|
|
8077
|
+
build_context_path: request.buildContextPath ?? ".",
|
|
8078
|
+
dependencies: request.dependencies ?? []
|
|
8079
|
+
});
|
|
8080
|
+
logger.debug(`Submitted build: ${data.build_id}`);
|
|
8081
|
+
return { buildId: data.build_id };
|
|
8082
|
+
}
|
|
8083
|
+
);
|
|
8084
|
+
},
|
|
8085
|
+
async list(options) {
|
|
8086
|
+
const { billingAddress, limit, offset } = options;
|
|
8087
|
+
return withSDKTelemetry(
|
|
8088
|
+
{
|
|
8089
|
+
functionName: "build.list",
|
|
8090
|
+
skipTelemetry,
|
|
8091
|
+
properties: {
|
|
8092
|
+
environment,
|
|
8093
|
+
billingAddress,
|
|
8094
|
+
...limit !== void 0 ? { limit: String(limit) } : {},
|
|
8095
|
+
...offset !== void 0 ? { offset: String(offset) } : {}
|
|
8096
|
+
}
|
|
8097
|
+
},
|
|
8098
|
+
async () => {
|
|
8099
|
+
const data = await api.listBuilds({
|
|
8100
|
+
billing_address: billingAddress,
|
|
8101
|
+
limit,
|
|
8102
|
+
offset
|
|
8103
|
+
});
|
|
8104
|
+
return Array.isArray(data) ? data.map(transformBuild) : [];
|
|
8105
|
+
}
|
|
8106
|
+
);
|
|
8107
|
+
},
|
|
8108
|
+
async get(buildId) {
|
|
8109
|
+
return withSDKTelemetry(
|
|
8110
|
+
{ functionName: "build.get", skipTelemetry, properties: { environment, buildId } },
|
|
8111
|
+
async () => transformBuild(await api.getBuild(buildId))
|
|
8112
|
+
);
|
|
8113
|
+
},
|
|
8114
|
+
async getByDigest(digest) {
|
|
8115
|
+
return withSDKTelemetry(
|
|
8116
|
+
{ functionName: "build.getByDigest", skipTelemetry, properties: { environment, digest } },
|
|
8117
|
+
async () => transformBuild(await api.getBuildByDigest(digest))
|
|
8118
|
+
);
|
|
8119
|
+
},
|
|
8120
|
+
async verify(identifier) {
|
|
8121
|
+
return withSDKTelemetry(
|
|
8122
|
+
{ functionName: "build.verify", skipTelemetry, properties: { environment, identifier } },
|
|
8123
|
+
async () => transformVerifyResult(await api.verify(identifier))
|
|
8124
|
+
);
|
|
8125
|
+
},
|
|
8126
|
+
async getLogs(buildId) {
|
|
8127
|
+
return withSDKTelemetry(
|
|
8128
|
+
{ functionName: "build.getLogs", skipTelemetry, properties: { environment, buildId } },
|
|
8129
|
+
async () => {
|
|
8130
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for getLogs()");
|
|
8131
|
+
return api.getLogs(buildId);
|
|
8132
|
+
}
|
|
8133
|
+
);
|
|
8134
|
+
},
|
|
8135
|
+
async submitAndWait(request, options = {}) {
|
|
8136
|
+
const { buildId } = await this.submit(request);
|
|
8137
|
+
return this.waitForBuild(buildId, options);
|
|
8138
|
+
},
|
|
8139
|
+
async waitForBuild(buildId, options = {}) {
|
|
8140
|
+
const {
|
|
8141
|
+
onLog,
|
|
8142
|
+
onProgress,
|
|
8143
|
+
pollIntervalMs = DEFAULT_POLL_INTERVAL,
|
|
8144
|
+
timeoutMs = DEFAULT_TIMEOUT
|
|
8145
|
+
} = options;
|
|
8146
|
+
const startTime = Date.now();
|
|
8147
|
+
let lastLogLength = 0;
|
|
8148
|
+
while (true) {
|
|
8149
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
8150
|
+
throw new TimeoutError(`Build timed out after ${timeoutMs}ms`);
|
|
8151
|
+
}
|
|
8152
|
+
const build = await this.get(buildId);
|
|
8153
|
+
let logs2 = "";
|
|
8154
|
+
try {
|
|
8155
|
+
logs2 = await this.getLogs(buildId);
|
|
8156
|
+
if (onLog && logs2.length > lastLogLength) {
|
|
8157
|
+
onLog(logs2.slice(lastLogLength));
|
|
8158
|
+
lastLogLength = logs2.length;
|
|
8159
|
+
}
|
|
8160
|
+
} catch {
|
|
8161
|
+
}
|
|
8162
|
+
onProgress?.({ build, logs: logs2 });
|
|
8163
|
+
if (build.status === BUILD_STATUS.SUCCESS) return build;
|
|
8164
|
+
if (build.status === BUILD_STATUS.FAILED) {
|
|
8165
|
+
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
8166
|
+
}
|
|
8167
|
+
await sleep2(pollIntervalMs);
|
|
8168
|
+
}
|
|
8169
|
+
},
|
|
8170
|
+
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
8171
|
+
let lastLength = 0;
|
|
8172
|
+
while (true) {
|
|
8173
|
+
const build = await this.get(buildId);
|
|
8174
|
+
let logs2 = "";
|
|
8175
|
+
try {
|
|
8176
|
+
logs2 = await this.getLogs(buildId);
|
|
8177
|
+
} catch {
|
|
8178
|
+
}
|
|
8179
|
+
if (logs2.length > lastLength) {
|
|
8180
|
+
yield {
|
|
8181
|
+
content: logs2.slice(lastLength),
|
|
8182
|
+
totalLength: logs2.length,
|
|
8183
|
+
isComplete: build.status !== BUILD_STATUS.BUILDING,
|
|
8184
|
+
finalStatus: build.status !== BUILD_STATUS.BUILDING ? build.status : void 0
|
|
8185
|
+
};
|
|
8186
|
+
lastLength = logs2.length;
|
|
8187
|
+
}
|
|
8188
|
+
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
8189
|
+
await sleep2(pollIntervalMs);
|
|
8190
|
+
}
|
|
8191
|
+
}
|
|
8192
|
+
};
|
|
8193
|
+
}
|
|
8194
|
+
function sleep2(ms) {
|
|
8195
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
8196
|
+
}
|
|
8197
|
+
function transformBuild(raw) {
|
|
8198
|
+
return {
|
|
8199
|
+
buildId: raw.build_id,
|
|
8200
|
+
billingAddress: raw.billing_address,
|
|
8201
|
+
repoUrl: raw.repo_url,
|
|
8202
|
+
gitRef: raw.git_ref,
|
|
8203
|
+
status: raw.status,
|
|
8204
|
+
buildType: raw.build_type,
|
|
8205
|
+
imageName: raw.image_name,
|
|
8206
|
+
imageUrl: raw.image_url,
|
|
8207
|
+
imageDigest: raw.image_digest,
|
|
8208
|
+
provenanceJson: raw.provenance_json ?? void 0,
|
|
8209
|
+
provenanceSignature: raw.provenance_signature ?? void 0,
|
|
8210
|
+
errorMessage: raw.error_message ?? void 0,
|
|
8211
|
+
createdAt: raw.created_at,
|
|
8212
|
+
updatedAt: raw.updated_at,
|
|
8213
|
+
dependencies: raw.dependencies ? Object.fromEntries(Object.entries(raw.dependencies).map(([k, v]) => [k, transformBuild(v)])) : void 0
|
|
8214
|
+
};
|
|
8215
|
+
}
|
|
8216
|
+
function transformVerifyResult(raw) {
|
|
8217
|
+
if (raw.status === "verified") {
|
|
8218
|
+
return {
|
|
8219
|
+
status: "verified",
|
|
8220
|
+
buildId: raw.build_id,
|
|
8221
|
+
imageUrl: raw.image_url,
|
|
8222
|
+
imageDigest: raw.image_digest,
|
|
8223
|
+
repoUrl: raw.repo_url,
|
|
8224
|
+
gitRef: raw.git_ref,
|
|
8225
|
+
provenanceJson: raw.provenance_json,
|
|
8226
|
+
provenanceSignature: raw.provenance_signature,
|
|
8227
|
+
payloadType: raw.payload_type,
|
|
8228
|
+
payload: raw.payload
|
|
8229
|
+
};
|
|
8230
|
+
}
|
|
8231
|
+
return {
|
|
8232
|
+
status: "failed",
|
|
8233
|
+
error: raw.error,
|
|
8234
|
+
buildId: raw.build_id
|
|
8235
|
+
};
|
|
8236
|
+
}
|
|
8237
|
+
|
|
7363
8238
|
// src/client/common/utils/instance.ts
|
|
7364
8239
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
7365
8240
|
try {
|
|
@@ -7414,10 +8289,20 @@ function createECloudClient(cfg) {
|
|
|
7414
8289
|
}
|
|
7415
8290
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7416
8291
|
0 && (module.exports = {
|
|
8292
|
+
AuthRequiredError,
|
|
8293
|
+
BUILD_STATUS,
|
|
8294
|
+
BadRequestError,
|
|
8295
|
+
BuildError,
|
|
8296
|
+
BuildFailedError,
|
|
8297
|
+
ConflictError,
|
|
8298
|
+
ForbiddenError,
|
|
7417
8299
|
NoopClient,
|
|
8300
|
+
NotFoundError,
|
|
7418
8301
|
PRIMARY_LANGUAGES,
|
|
7419
8302
|
PostHogClient,
|
|
8303
|
+
TimeoutError,
|
|
7420
8304
|
UserApiClient,
|
|
8305
|
+
addHexPrefix,
|
|
7421
8306
|
addMetric,
|
|
7422
8307
|
addMetricWithDimensions,
|
|
7423
8308
|
assertValidFilePath,
|
|
@@ -7427,6 +8312,7 @@ function createECloudClient(cfg) {
|
|
|
7427
8312
|
createApp,
|
|
7428
8313
|
createAppEnvironment,
|
|
7429
8314
|
createBillingModule,
|
|
8315
|
+
createBuildModule,
|
|
7430
8316
|
createComputeModule,
|
|
7431
8317
|
createECloudClient,
|
|
7432
8318
|
createMetricsContext,
|
|
@@ -7470,12 +8356,15 @@ function createECloudClient(cfg) {
|
|
|
7470
8356
|
listStoredKeys,
|
|
7471
8357
|
logs,
|
|
7472
8358
|
prepareDeploy,
|
|
8359
|
+
prepareDeployFromVerifiableBuild,
|
|
7473
8360
|
prepareUpgrade,
|
|
8361
|
+
prepareUpgradeFromVerifiableBuild,
|
|
7474
8362
|
requirePrivateKey,
|
|
7475
8363
|
sanitizeString,
|
|
7476
8364
|
sanitizeURL,
|
|
7477
8365
|
sanitizeXURL,
|
|
7478
8366
|
storePrivateKey,
|
|
8367
|
+
stripHexPrefix,
|
|
7479
8368
|
validateAppID,
|
|
7480
8369
|
validateAppName,
|
|
7481
8370
|
validateCreateAppParams,
|