@layr-labs/ecloud-sdk 0.1.2 → 0.2.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +2 -2
- package/dist/billing.cjs +1 -1
- 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-AOZRDBLK.js → chunk-FY7UU55U.js} +107 -31
- package/dist/chunk-FY7UU55U.js.map +1 -0
- package/dist/{chunk-4RG5IMZ7.js → chunk-GB4GM4C2.js} +2 -2
- package/dist/{chunk-MQ2NGP4C.js → chunk-O7EU5JL7.js} +312 -55
- package/dist/chunk-O7EU5JL7.js.map +1 -0
- package/dist/{compute-BlUpqWKo.d.cts → compute-CF2HOXed.d.ts} +9 -1
- package/dist/{compute-CottWiST.d.ts → compute-CbmjA8kJ.d.cts} +9 -1
- package/dist/compute.cjs +387 -47
- 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-Fb_S-Cqk.d.ts → index-D2QufVB9.d.cts} +33 -1
- package/dist/{index-Fb_S-Cqk.d.cts → index-D2QufVB9.d.ts} +33 -1
- package/dist/index.cjs +769 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +314 -98
- package/dist/index.d.ts +314 -98
- package/dist/index.js +376 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-AOZRDBLK.js.map +0 -1
- package/dist/chunk-MQ2NGP4C.js.map +0 -1
- /package/dist/{chunk-4RG5IMZ7.js.map → chunk-GB4GM4C2.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
requirePrivateKey,
|
|
14
14
|
storePrivateKey,
|
|
15
15
|
validatePrivateKey
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GB4GM4C2.js";
|
|
17
17
|
import {
|
|
18
18
|
PRIMARY_LANGUAGES,
|
|
19
19
|
assertValidFilePath,
|
|
@@ -40,7 +40,9 @@ import {
|
|
|
40
40
|
getTemplate,
|
|
41
41
|
logs,
|
|
42
42
|
prepareDeploy,
|
|
43
|
+
prepareDeployFromVerifiableBuild,
|
|
43
44
|
prepareUpgrade,
|
|
45
|
+
prepareUpgradeFromVerifiableBuild,
|
|
44
46
|
sanitizeString,
|
|
45
47
|
sanitizeURL,
|
|
46
48
|
sanitizeXURL,
|
|
@@ -62,7 +64,7 @@ import {
|
|
|
62
64
|
validateXURL,
|
|
63
65
|
watchDeployment,
|
|
64
66
|
watchUpgrade
|
|
65
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-O7EU5JL7.js";
|
|
66
68
|
import {
|
|
67
69
|
NoopClient,
|
|
68
70
|
PostHogClient,
|
|
@@ -70,6 +72,7 @@ import {
|
|
|
70
72
|
addHexPrefix,
|
|
71
73
|
addMetric,
|
|
72
74
|
addMetricWithDimensions,
|
|
75
|
+
calculateBillingAuthSignature,
|
|
73
76
|
createAppEnvironment,
|
|
74
77
|
createMetricsContext,
|
|
75
78
|
createTelemetryClient,
|
|
@@ -77,14 +80,370 @@ import {
|
|
|
77
80
|
getAvailableEnvironments,
|
|
78
81
|
getBuildType,
|
|
79
82
|
getEnvironmentConfig,
|
|
83
|
+
getLogger,
|
|
80
84
|
getPostHogAPIKey,
|
|
81
85
|
getPostHogEndpoint,
|
|
82
86
|
isEnvironmentAvailable,
|
|
83
87
|
isMainnet,
|
|
84
88
|
isNoopClient,
|
|
85
89
|
isSubscriptionActive,
|
|
90
|
+
stripHexPrefix,
|
|
86
91
|
withSDKTelemetry
|
|
87
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-FY7UU55U.js";
|
|
93
|
+
|
|
94
|
+
// src/client/common/utils/buildapi.ts
|
|
95
|
+
import axios from "axios";
|
|
96
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
97
|
+
var BuildApiClient = class {
|
|
98
|
+
constructor(options) {
|
|
99
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
100
|
+
this.clientId = options.clientId;
|
|
101
|
+
if (options.privateKey) {
|
|
102
|
+
this.account = privateKeyToAccount(options.privateKey);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async submitBuild(payload) {
|
|
106
|
+
return this.authenticatedJsonRequest("/builds", "POST", payload);
|
|
107
|
+
}
|
|
108
|
+
async getBuild(buildId) {
|
|
109
|
+
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
110
|
+
}
|
|
111
|
+
async getBuildByDigest(digest) {
|
|
112
|
+
return this.publicJsonRequest(`/builds/image/${encodeURIComponent(digest)}`);
|
|
113
|
+
}
|
|
114
|
+
async verify(identifier) {
|
|
115
|
+
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
116
|
+
}
|
|
117
|
+
async getLogs(buildId) {
|
|
118
|
+
return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
119
|
+
}
|
|
120
|
+
async listBuilds(params) {
|
|
121
|
+
const res = await axios({
|
|
122
|
+
url: `${this.baseUrl}/builds`,
|
|
123
|
+
method: "GET",
|
|
124
|
+
params,
|
|
125
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
126
|
+
timeout: 6e4,
|
|
127
|
+
validateStatus: () => true
|
|
128
|
+
});
|
|
129
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
130
|
+
return res.data;
|
|
131
|
+
}
|
|
132
|
+
async publicJsonRequest(path) {
|
|
133
|
+
const res = await axios({
|
|
134
|
+
url: `${this.baseUrl}${path}`,
|
|
135
|
+
method: "GET",
|
|
136
|
+
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
137
|
+
timeout: 6e4,
|
|
138
|
+
validateStatus: () => true
|
|
139
|
+
});
|
|
140
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
141
|
+
return res.data;
|
|
142
|
+
}
|
|
143
|
+
async authenticatedJsonRequest(path, method, body) {
|
|
144
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
145
|
+
const headers = {
|
|
146
|
+
"Content-Type": "application/json"
|
|
147
|
+
};
|
|
148
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
149
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
150
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
151
|
+
account: this.account,
|
|
152
|
+
product: "compute",
|
|
153
|
+
expiry
|
|
154
|
+
});
|
|
155
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
156
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
157
|
+
headers["X-Account"] = this.account.address;
|
|
158
|
+
const res = await axios({
|
|
159
|
+
url: `${this.baseUrl}${path}`,
|
|
160
|
+
method,
|
|
161
|
+
headers,
|
|
162
|
+
data: body,
|
|
163
|
+
timeout: 6e4,
|
|
164
|
+
validateStatus: () => true
|
|
165
|
+
});
|
|
166
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
167
|
+
return res.data;
|
|
168
|
+
}
|
|
169
|
+
async authenticatedTextRequest(path) {
|
|
170
|
+
if (!this.account) throw new Error("Private key required for authenticated requests");
|
|
171
|
+
const headers = {};
|
|
172
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
173
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
174
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
175
|
+
account: this.account,
|
|
176
|
+
product: "compute",
|
|
177
|
+
expiry
|
|
178
|
+
});
|
|
179
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
180
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
181
|
+
headers["X-Account"] = this.account.address;
|
|
182
|
+
const res = await axios({
|
|
183
|
+
url: `${this.baseUrl}${path}`,
|
|
184
|
+
method: "GET",
|
|
185
|
+
headers,
|
|
186
|
+
timeout: 6e4,
|
|
187
|
+
responseType: "text",
|
|
188
|
+
validateStatus: () => true
|
|
189
|
+
});
|
|
190
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
191
|
+
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
function buildApiHttpError(res) {
|
|
195
|
+
const status = res.status;
|
|
196
|
+
const body = typeof res.data === "string" ? res.data : res.data ? JSON.stringify(res.data) : "";
|
|
197
|
+
const url = res.config?.url ? ` ${res.config.url}` : "";
|
|
198
|
+
return new Error(`BuildAPI request failed: ${status}${url} - ${body || "Unknown error"}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/client/modules/build/types.ts
|
|
202
|
+
var BUILD_STATUS = {
|
|
203
|
+
BUILDING: "building",
|
|
204
|
+
SUCCESS: "success",
|
|
205
|
+
FAILED: "failed"
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// src/client/modules/build/errors.ts
|
|
209
|
+
var BuildError = class extends Error {
|
|
210
|
+
constructor(message) {
|
|
211
|
+
super(message);
|
|
212
|
+
this.name = "BuildError";
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
var AuthRequiredError = class extends BuildError {
|
|
216
|
+
constructor(message = "Authentication required") {
|
|
217
|
+
super(message);
|
|
218
|
+
this.name = "AuthRequiredError";
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
var BuildFailedError = class extends BuildError {
|
|
222
|
+
constructor(message, buildId) {
|
|
223
|
+
super(message);
|
|
224
|
+
this.buildId = buildId;
|
|
225
|
+
this.name = "BuildFailedError";
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
var ConflictError = class extends BuildError {
|
|
229
|
+
constructor(message = "Build already in progress") {
|
|
230
|
+
super(message);
|
|
231
|
+
this.name = "ConflictError";
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var NotFoundError = class extends BuildError {
|
|
235
|
+
constructor(message = "Build not found") {
|
|
236
|
+
super(message);
|
|
237
|
+
this.name = "NotFoundError";
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
var ForbiddenError = class extends BuildError {
|
|
241
|
+
constructor(message = "Permission denied") {
|
|
242
|
+
super(message);
|
|
243
|
+
this.name = "ForbiddenError";
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
var TimeoutError = class extends BuildError {
|
|
247
|
+
constructor(message = "Operation timed out") {
|
|
248
|
+
super(message);
|
|
249
|
+
this.name = "TimeoutError";
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
var BadRequestError = class extends BuildError {
|
|
253
|
+
constructor(message = "Bad request") {
|
|
254
|
+
super(message);
|
|
255
|
+
this.name = "BadRequestError";
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// src/client/modules/build/index.ts
|
|
260
|
+
var DEFAULT_POLL_INTERVAL = 2e3;
|
|
261
|
+
var DEFAULT_TIMEOUT = 30 * 60 * 1e3;
|
|
262
|
+
function createBuildModule(config) {
|
|
263
|
+
const { verbose = false, skipTelemetry = false } = config;
|
|
264
|
+
const logger = getLogger(verbose);
|
|
265
|
+
const environment = config.environment || "sepolia";
|
|
266
|
+
const environmentConfig = getEnvironmentConfig(environment);
|
|
267
|
+
const api = new BuildApiClient({
|
|
268
|
+
baseUrl: environmentConfig.userApiServerURL,
|
|
269
|
+
privateKey: config.privateKey ? addHexPrefix(config.privateKey) : void 0,
|
|
270
|
+
clientId: config.clientId
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
async submit(request) {
|
|
274
|
+
return withSDKTelemetry(
|
|
275
|
+
{
|
|
276
|
+
functionName: "build.submit",
|
|
277
|
+
skipTelemetry,
|
|
278
|
+
properties: { environment, repoUrl: request.repoUrl }
|
|
279
|
+
},
|
|
280
|
+
async () => {
|
|
281
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for submit()");
|
|
282
|
+
const data = await api.submitBuild({
|
|
283
|
+
repo_url: request.repoUrl,
|
|
284
|
+
git_ref: request.gitRef,
|
|
285
|
+
dockerfile_path: request.dockerfilePath ?? "Dockerfile",
|
|
286
|
+
caddyfile_path: request.caddyfilePath,
|
|
287
|
+
build_context_path: request.buildContextPath ?? ".",
|
|
288
|
+
dependencies: request.dependencies ?? []
|
|
289
|
+
});
|
|
290
|
+
logger.debug(`Submitted build: ${data.build_id}`);
|
|
291
|
+
return { buildId: data.build_id };
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
},
|
|
295
|
+
async list(options) {
|
|
296
|
+
const { billingAddress, limit, offset } = options;
|
|
297
|
+
return withSDKTelemetry(
|
|
298
|
+
{
|
|
299
|
+
functionName: "build.list",
|
|
300
|
+
skipTelemetry,
|
|
301
|
+
properties: {
|
|
302
|
+
environment,
|
|
303
|
+
billingAddress,
|
|
304
|
+
...limit !== void 0 ? { limit: String(limit) } : {},
|
|
305
|
+
...offset !== void 0 ? { offset: String(offset) } : {}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
async () => {
|
|
309
|
+
const data = await api.listBuilds({
|
|
310
|
+
billing_address: billingAddress,
|
|
311
|
+
limit,
|
|
312
|
+
offset
|
|
313
|
+
});
|
|
314
|
+
return Array.isArray(data) ? data.map(transformBuild) : [];
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
},
|
|
318
|
+
async get(buildId) {
|
|
319
|
+
return withSDKTelemetry(
|
|
320
|
+
{ functionName: "build.get", skipTelemetry, properties: { environment, buildId } },
|
|
321
|
+
async () => transformBuild(await api.getBuild(buildId))
|
|
322
|
+
);
|
|
323
|
+
},
|
|
324
|
+
async getByDigest(digest) {
|
|
325
|
+
return withSDKTelemetry(
|
|
326
|
+
{ functionName: "build.getByDigest", skipTelemetry, properties: { environment, digest } },
|
|
327
|
+
async () => transformBuild(await api.getBuildByDigest(digest))
|
|
328
|
+
);
|
|
329
|
+
},
|
|
330
|
+
async verify(identifier) {
|
|
331
|
+
return withSDKTelemetry(
|
|
332
|
+
{ functionName: "build.verify", skipTelemetry, properties: { environment, identifier } },
|
|
333
|
+
async () => transformVerifyResult(await api.verify(identifier))
|
|
334
|
+
);
|
|
335
|
+
},
|
|
336
|
+
async getLogs(buildId) {
|
|
337
|
+
return withSDKTelemetry(
|
|
338
|
+
{ functionName: "build.getLogs", skipTelemetry, properties: { environment, buildId } },
|
|
339
|
+
async () => {
|
|
340
|
+
if (!config.privateKey) throw new AuthRequiredError("Private key required for getLogs()");
|
|
341
|
+
return api.getLogs(buildId);
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
},
|
|
345
|
+
async submitAndWait(request, options = {}) {
|
|
346
|
+
const { buildId } = await this.submit(request);
|
|
347
|
+
return this.waitForBuild(buildId, options);
|
|
348
|
+
},
|
|
349
|
+
async waitForBuild(buildId, options = {}) {
|
|
350
|
+
const {
|
|
351
|
+
onLog,
|
|
352
|
+
onProgress,
|
|
353
|
+
pollIntervalMs = DEFAULT_POLL_INTERVAL,
|
|
354
|
+
timeoutMs = DEFAULT_TIMEOUT
|
|
355
|
+
} = options;
|
|
356
|
+
const startTime = Date.now();
|
|
357
|
+
let lastLogLength = 0;
|
|
358
|
+
while (true) {
|
|
359
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
360
|
+
throw new TimeoutError(`Build timed out after ${timeoutMs}ms`);
|
|
361
|
+
}
|
|
362
|
+
const build = await this.get(buildId);
|
|
363
|
+
let logs2 = "";
|
|
364
|
+
try {
|
|
365
|
+
logs2 = await this.getLogs(buildId);
|
|
366
|
+
if (onLog && logs2.length > lastLogLength) {
|
|
367
|
+
onLog(logs2.slice(lastLogLength));
|
|
368
|
+
lastLogLength = logs2.length;
|
|
369
|
+
}
|
|
370
|
+
} catch {
|
|
371
|
+
}
|
|
372
|
+
onProgress?.({ build, logs: logs2 });
|
|
373
|
+
if (build.status === BUILD_STATUS.SUCCESS) return build;
|
|
374
|
+
if (build.status === BUILD_STATUS.FAILED) {
|
|
375
|
+
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
376
|
+
}
|
|
377
|
+
await sleep(pollIntervalMs);
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
381
|
+
let lastLength = 0;
|
|
382
|
+
while (true) {
|
|
383
|
+
const build = await this.get(buildId);
|
|
384
|
+
let logs2 = "";
|
|
385
|
+
try {
|
|
386
|
+
logs2 = await this.getLogs(buildId);
|
|
387
|
+
} catch {
|
|
388
|
+
}
|
|
389
|
+
if (logs2.length > lastLength) {
|
|
390
|
+
yield {
|
|
391
|
+
content: logs2.slice(lastLength),
|
|
392
|
+
totalLength: logs2.length,
|
|
393
|
+
isComplete: build.status !== BUILD_STATUS.BUILDING,
|
|
394
|
+
finalStatus: build.status !== BUILD_STATUS.BUILDING ? build.status : void 0
|
|
395
|
+
};
|
|
396
|
+
lastLength = logs2.length;
|
|
397
|
+
}
|
|
398
|
+
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
399
|
+
await sleep(pollIntervalMs);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function sleep(ms) {
|
|
405
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
406
|
+
}
|
|
407
|
+
function transformBuild(raw) {
|
|
408
|
+
return {
|
|
409
|
+
buildId: raw.build_id,
|
|
410
|
+
billingAddress: raw.billing_address,
|
|
411
|
+
repoUrl: raw.repo_url,
|
|
412
|
+
gitRef: raw.git_ref,
|
|
413
|
+
status: raw.status,
|
|
414
|
+
buildType: raw.build_type,
|
|
415
|
+
imageName: raw.image_name,
|
|
416
|
+
imageUrl: raw.image_url,
|
|
417
|
+
imageDigest: raw.image_digest,
|
|
418
|
+
provenanceJson: raw.provenance_json ?? void 0,
|
|
419
|
+
provenanceSignature: raw.provenance_signature ?? void 0,
|
|
420
|
+
errorMessage: raw.error_message ?? void 0,
|
|
421
|
+
createdAt: raw.created_at,
|
|
422
|
+
updatedAt: raw.updated_at,
|
|
423
|
+
dependencies: raw.dependencies ? Object.fromEntries(Object.entries(raw.dependencies).map(([k, v]) => [k, transformBuild(v)])) : void 0
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function transformVerifyResult(raw) {
|
|
427
|
+
if (raw.status === "verified") {
|
|
428
|
+
return {
|
|
429
|
+
status: "verified",
|
|
430
|
+
buildId: raw.build_id,
|
|
431
|
+
imageUrl: raw.image_url,
|
|
432
|
+
imageDigest: raw.image_digest,
|
|
433
|
+
repoUrl: raw.repo_url,
|
|
434
|
+
gitRef: raw.git_ref,
|
|
435
|
+
provenanceJson: raw.provenance_json,
|
|
436
|
+
provenanceSignature: raw.provenance_signature,
|
|
437
|
+
payloadType: raw.payload_type,
|
|
438
|
+
payload: raw.payload
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
status: "failed",
|
|
443
|
+
error: raw.error,
|
|
444
|
+
buildId: raw.build_id
|
|
445
|
+
};
|
|
446
|
+
}
|
|
88
447
|
|
|
89
448
|
// src/client/common/utils/instance.ts
|
|
90
449
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
@@ -139,10 +498,20 @@ function createECloudClient(cfg) {
|
|
|
139
498
|
};
|
|
140
499
|
}
|
|
141
500
|
export {
|
|
501
|
+
AuthRequiredError,
|
|
502
|
+
BUILD_STATUS,
|
|
503
|
+
BadRequestError,
|
|
504
|
+
BuildError,
|
|
505
|
+
BuildFailedError,
|
|
506
|
+
ConflictError,
|
|
507
|
+
ForbiddenError,
|
|
142
508
|
NoopClient,
|
|
509
|
+
NotFoundError,
|
|
143
510
|
PRIMARY_LANGUAGES,
|
|
144
511
|
PostHogClient,
|
|
512
|
+
TimeoutError,
|
|
145
513
|
UserApiClient,
|
|
514
|
+
addHexPrefix,
|
|
146
515
|
addMetric,
|
|
147
516
|
addMetricWithDimensions,
|
|
148
517
|
assertValidFilePath,
|
|
@@ -152,6 +521,7 @@ export {
|
|
|
152
521
|
createApp,
|
|
153
522
|
createAppEnvironment,
|
|
154
523
|
createBillingModule,
|
|
524
|
+
createBuildModule,
|
|
155
525
|
createComputeModule,
|
|
156
526
|
createECloudClient,
|
|
157
527
|
createMetricsContext,
|
|
@@ -195,12 +565,15 @@ export {
|
|
|
195
565
|
listStoredKeys,
|
|
196
566
|
logs,
|
|
197
567
|
prepareDeploy,
|
|
568
|
+
prepareDeployFromVerifiableBuild,
|
|
198
569
|
prepareUpgrade,
|
|
570
|
+
prepareUpgradeFromVerifiableBuild,
|
|
199
571
|
requirePrivateKey,
|
|
200
572
|
sanitizeString,
|
|
201
573
|
sanitizeURL,
|
|
202
574
|
sanitizeXURL,
|
|
203
575
|
storePrivateKey,
|
|
576
|
+
stripHexPrefix,
|
|
204
577
|
validateAppID,
|
|
205
578
|
validateAppName,
|
|
206
579
|
validateCreateAppParams,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/common/utils/instance.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Instance type utilities\n */\n\nimport { Address } from \"viem\";\nimport { PreflightContext } from \"./preflight\";\nimport { Logger } from \"../types\";\nimport { UserApiClient } from \"./userapi\";\n\n/**\n * Get current instance type for an app (best-effort)\n * Returns empty string if unable to fetch (API unavailable, app info not ready, etc.).\n * This is used as a convenience default for the upgrade flow.\n */\nexport async function getCurrentInstanceType(\n preflightCtx: PreflightContext,\n appID: Address,\n logger: Logger,\n clientId?: string,\n): Promise<string> {\n try {\n const userApiClient = new UserApiClient(\n preflightCtx.environmentConfig,\n preflightCtx.privateKey,\n preflightCtx.rpcUrl,\n clientId,\n );\n\n const infos = await userApiClient.getInfos([appID], 1);\n if (infos.length === 0) {\n return \"\"; // No app info available yet\n }\n\n return infos[0].machineType || \"\";\n } catch (err: any) {\n logger.debug(`Failed to get current instance type: ${err.message}`);\n return \"\"; // API call failed, skip default\n }\n}\n","/**\n * Main SDK Client entry point\n */\n\nimport { createComputeModule, type ComputeModule } from \"./modules/compute\";\nimport {\n getEnvironmentConfig,\n isEnvironmentAvailable,\n getAvailableEnvironments,\n} from \"./common/config/environment\";\nimport { createBillingModule, type BillingModule } from \"./modules/billing\";\nimport { addHexPrefix } from \"./common/utils\";\nimport { Hex } from \"viem\";\n\n// Export all types\nexport * from \"./common/types\";\n\n// Export validation utilities (non-interactive)\nexport * from \"./common/utils/validation\";\n\n// Special case on createApp - we don't need the client to run it\nexport {\n createApp,\n CreateAppOpts,\n SDKCreateAppOpts,\n PRIMARY_LANGUAGES,\n getAvailableTemplates,\n} from \"./modules/compute/app/create\";\nexport { logs, LogsOptions, SDKLogsOptions } from \"./modules/compute/app/logs\";\nexport {\n SDKDeployOptions,\n prepareDeploy,\n executeDeploy,\n watchDeployment,\n type PrepareDeployResult,\n} from \"./modules/compute/app/deploy\";\nexport {\n SDKUpgradeOptions,\n prepareUpgrade,\n executeUpgrade,\n watchUpgrade,\n type PrepareUpgradeResult,\n} from \"./modules/compute/app/upgrade\";\n\n// Export compute module for standalone use\nexport {\n createComputeModule,\n type ComputeModule,\n type ComputeModuleConfig,\n encodeStartAppData,\n encodeStopAppData,\n encodeTerminateAppData,\n} from \"./modules/compute\";\nexport {\n createBillingModule,\n type BillingModule,\n type BillingModuleConfig,\n} from \"./modules/billing\";\n\n// Export environment config utilities\nexport {\n getEnvironmentConfig,\n getAvailableEnvironments,\n isEnvironmentAvailable,\n getBuildType,\n isMainnet,\n} from \"./common/config/environment\";\nexport { isSubscriptionActive } from \"./common/utils/billing\";\n\n// Export auth utilities\nexport * from \"./common/auth\";\n\n// Export telemetry\nexport * from \"./common/telemetry\";\n\n// Export template catalog utilities for CLI\nexport {\n fetchTemplateCatalog,\n getTemplate,\n getCategoryDescriptions,\n} from \"./common/templates/catalog\";\n\n// Export contract utilities\nexport {\n getAllAppsByDeveloper,\n getAppLatestReleaseBlockNumbers,\n getBlockTimestamps,\n estimateTransactionGas,\n formatETH,\n type GasEstimate,\n type EstimateGasOptions,\n} from \"./common/contract/caller\";\n\n// Export batch gas estimation and delegation check\nexport {\n estimateBatchGas,\n checkERC7702Delegation,\n type EstimateBatchGasOptions,\n} from \"./common/contract/eip7702\";\n\n// Export instance type utilities\nexport { getCurrentInstanceType } from \"./common/utils/instance\";\n\n// Export user API client\nexport {\n UserApiClient,\n type AppInfo,\n type AppProfileInfo,\n type AppMetrics,\n} from \"./common/utils/userapi\";\n\nexport type Environment = \"sepolia\" | \"sepolia-dev\" | \"mainnet-alpha\";\n\nexport interface ClientConfig {\n verbose: boolean;\n privateKey: Hex;\n environment: Environment | string;\n rpcUrl?: string;\n}\n\nexport interface ECloudClient {\n compute: ComputeModule;\n billing: BillingModule;\n}\n\nexport function createECloudClient(cfg: ClientConfig): ECloudClient {\n cfg.privateKey = addHexPrefix(cfg.privateKey);\n\n // Validate environment is available in current build\n const environment = cfg.environment || \"sepolia\";\n if (!isEnvironmentAvailable(environment)) {\n throw new Error(\n `Environment \"${environment}\" is not available in this build type. ` +\n `Available environments: ${getAvailableEnvironments().join(\", \")}`,\n );\n }\n\n // Get environment config\n const environmentConfig = getEnvironmentConfig(environment);\n\n // Get rpc url from environment config or use provided rpc url\n let rpcUrl = cfg.rpcUrl;\n if (!rpcUrl) {\n rpcUrl = process.env.RPC_URL ?? environmentConfig.defaultRPCURL;\n }\n if (!rpcUrl) {\n throw new Error(\n `RPC URL is required. Provide via options.rpcUrl, RPC_URL env var, or ensure environment has default RPC URL`,\n );\n }\n\n return {\n compute: createComputeModule({\n rpcUrl,\n verbose: cfg.verbose,\n privateKey: cfg.privateKey,\n environment: cfg.environment,\n }),\n billing: createBillingModule({\n verbose: cfg.verbose,\n privateKey: cfg.privateKey,\n }),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,eAAsB,uBACpB,cACA,OACA,QACA,UACiB;AACjB,MAAI;AACF,UAAM,gBAAgB,IAAI;AAAA,MACxB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,MACb;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,cAAc,SAAS,CAAC,KAAK,GAAG,CAAC;AACrD,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,CAAC,EAAE,eAAe;AAAA,EACjC,SAAS,KAAU;AACjB,WAAO,MAAM,wCAAwC,IAAI,OAAO,EAAE;AAClE,WAAO;AAAA,EACT;AACF;;;ACuFO,SAAS,mBAAmB,KAAiC;AAClE,MAAI,aAAa,aAAa,IAAI,UAAU;AAG5C,QAAM,cAAc,IAAI,eAAe;AACvC,MAAI,CAAC,uBAAuB,WAAW,GAAG;AACxC,UAAM,IAAI;AAAA,MACR,gBAAgB,WAAW,kEACE,yBAAyB,EAAE,KAAK,IAAI,CAAC;AAAA,IACpE;AAAA,EACF;AAGA,QAAM,oBAAoB,qBAAqB,WAAW;AAG1D,MAAI,SAAS,IAAI;AACjB,MAAI,CAAC,QAAQ;AACX,aAAS,QAAQ,IAAI,WAAW,kBAAkB;AAAA,EACpD;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,oBAAoB;AAAA,MAC3B;AAAA,MACA,SAAS,IAAI;AAAA,MACb,YAAY,IAAI;AAAA,MAChB,aAAa,IAAI;AAAA,IACnB,CAAC;AAAA,IACD,SAAS,oBAAoB;AAAA,MAC3B,SAAS,IAAI;AAAA,MACb,YAAY,IAAI;AAAA,IAClB,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client/common/utils/buildapi.ts","../src/client/modules/build/types.ts","../src/client/modules/build/errors.ts","../src/client/modules/build/index.ts","../src/client/common/utils/instance.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Build API Client to manage verifiable builds and provenance\n *\n * This is a standalone HTTP client that talks to the (compute) UserAPI host.\n */\n\nimport axios, { AxiosResponse } from \"axios\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nimport type { Hex } from \"viem\";\nimport { calculateBillingAuthSignature } from \"./auth\";\n\nexport class BuildApiClient {\n private readonly baseUrl: string;\n private readonly account?: ReturnType<typeof privateKeyToAccount>;\n private readonly clientId?: string;\n\n constructor(options: { baseUrl: string; privateKey?: Hex | string; clientId?: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.clientId = options.clientId;\n\n if (options.privateKey) {\n this.account = privateKeyToAccount(options.privateKey as Hex);\n }\n }\n\n async submitBuild(payload: {\n repo_url: string;\n git_ref: string;\n dockerfile_path: string;\n caddyfile_path?: string;\n build_context_path: string;\n dependencies: string[];\n }): Promise<{ build_id: string }> {\n return this.authenticatedJsonRequest<{ build_id: string }>(\"/builds\", \"POST\", payload);\n }\n\n async getBuild(buildId: string): Promise<any> {\n return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);\n }\n\n async getBuildByDigest(digest: string): Promise<any> {\n return this.publicJsonRequest(`/builds/image/${encodeURIComponent(digest)}`);\n }\n\n async verify(identifier: string): Promise<any> {\n return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);\n }\n\n async getLogs(buildId: string): Promise<string> {\n return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);\n }\n\n async listBuilds(params: {\n billing_address: string;\n limit?: number;\n offset?: number;\n }): Promise<any[]> {\n const res: AxiosResponse = await axios({\n url: `${this.baseUrl}/builds`,\n method: \"GET\",\n params,\n headers: this.clientId ? { \"x-client-id\": this.clientId } : undefined,\n timeout: 60_000,\n validateStatus: () => true,\n });\n if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);\n return res.data as any[];\n }\n\n private async publicJsonRequest(path: string): Promise<any> {\n const res: AxiosResponse = await axios({\n url: `${this.baseUrl}${path}`,\n method: \"GET\",\n headers: this.clientId ? { \"x-client-id\": this.clientId } : undefined,\n timeout: 60_000,\n validateStatus: () => true,\n });\n if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);\n return res.data;\n }\n\n private async authenticatedJsonRequest<T>(\n path: string,\n method: \"POST\" | \"GET\",\n body?: unknown,\n ): Promise<T> {\n if (!this.account) throw new Error(\"Private key required for authenticated requests\");\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.clientId) headers[\"x-client-id\"] = this.clientId;\n\n // Builds API uses BillingAuth signature format (same as Billing API).\n // Keep expiry short to reduce replay window.\n const expiry = BigInt(Math.floor(Date.now() / 1000) + 60);\n const { signature } = await calculateBillingAuthSignature({\n account: this.account,\n product: \"compute\",\n expiry,\n });\n headers.Authorization = `Bearer ${signature}`;\n headers[\"X-eigenx-expiry\"] = expiry.toString();\n headers[\"X-Account\"] = this.account.address;\n\n const res: AxiosResponse = await axios({\n url: `${this.baseUrl}${path}`,\n method,\n headers,\n data: body,\n timeout: 60_000,\n validateStatus: () => true,\n });\n if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);\n return res.data as T;\n }\n\n private async authenticatedTextRequest(path: string): Promise<string> {\n if (!this.account) throw new Error(\"Private key required for authenticated requests\");\n\n const headers: Record<string, string> = {};\n if (this.clientId) headers[\"x-client-id\"] = this.clientId;\n\n const expiry = BigInt(Math.floor(Date.now() / 1000) + 60);\n const { signature } = await calculateBillingAuthSignature({\n account: this.account,\n product: \"compute\",\n expiry,\n });\n headers.Authorization = `Bearer ${signature}`;\n headers[\"X-eigenx-expiry\"] = expiry.toString();\n headers[\"X-Account\"] = this.account.address;\n\n const res: AxiosResponse = await axios({\n url: `${this.baseUrl}${path}`,\n method: \"GET\",\n headers,\n timeout: 60_000,\n responseType: \"text\",\n validateStatus: () => true,\n });\n if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);\n return typeof res.data === \"string\" ? res.data : JSON.stringify(res.data);\n }\n}\n\nfunction buildApiHttpError(res: AxiosResponse): Error {\n const status = res.status;\n const body = typeof res.data === \"string\" ? res.data : res.data ? JSON.stringify(res.data) : \"\";\n const url = res.config?.url ? ` ${res.config.url}` : \"\";\n return new Error(`BuildAPI request failed: ${status}${url} - ${body || \"Unknown error\"}`);\n}\n","// ============ Request/Response Types ============\n\nexport interface SubmitBuildRequest {\n repoUrl: string;\n gitRef: string;\n dockerfilePath?: string;\n /**\n * Path to a Caddyfile within the repository (relative to buildContextPath).\n * If omitted, the build service will not copy a Caddyfile into the image.\n */\n caddyfilePath?: string;\n buildContextPath?: string;\n dependencies?: string[];\n}\n\nexport interface SubmitBuildResponse {\n buildId: string;\n}\n\nexport const BUILD_STATUS = {\n BUILDING: \"building\",\n SUCCESS: \"success\",\n FAILED: \"failed\",\n} as const;\n\nexport type BuildStatus = (typeof BUILD_STATUS)[keyof typeof BUILD_STATUS];\n\nexport interface Build {\n buildId: string;\n billingAddress: string;\n repoUrl: string;\n gitRef: string;\n status: BuildStatus;\n /** 'application' | 'dependency' (as returned by the API) */\n buildType: string;\n imageName: string;\n imageUrl?: string;\n imageDigest?: string;\n provenanceJson?: Record<string, unknown>;\n provenanceSignature?: string;\n errorMessage?: string;\n createdAt: string;\n updatedAt: string;\n dependencies?: Record<string, Build>;\n}\n\n// ============ Verification Types ============\n\nexport type VerifyProvenanceResult = VerifyProvenanceSuccess | VerifyProvenanceFailure;\n\nexport interface VerifyProvenanceSuccess {\n status: \"verified\";\n buildId: string;\n imageUrl: string;\n imageDigest: string;\n repoUrl: string;\n gitRef: string;\n provenanceJson: Record<string, unknown>;\n provenanceSignature: string;\n payloadType: string;\n payload: string;\n}\n\nexport interface VerifyProvenanceFailure {\n status: \"failed\";\n error: string;\n buildId?: string;\n}\n\n// ============ Log Streaming ============\n\nexport interface LogChunk {\n content: string;\n totalLength: number;\n isComplete: boolean;\n finalStatus?: BuildStatus;\n}\n\nexport interface BuildProgress {\n build: Build;\n logs: string;\n}\n","export class BuildError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BuildError\";\n }\n}\n\nexport class AuthRequiredError extends BuildError {\n constructor(message = \"Authentication required\") {\n super(message);\n this.name = \"AuthRequiredError\";\n }\n}\n\nexport class BuildFailedError extends BuildError {\n constructor(\n message: string,\n public readonly buildId: string,\n ) {\n super(message);\n this.name = \"BuildFailedError\";\n }\n}\n\nexport class ConflictError extends BuildError {\n constructor(message = \"Build already in progress\") {\n super(message);\n this.name = \"ConflictError\";\n }\n}\n\nexport class NotFoundError extends BuildError {\n constructor(message = \"Build not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ForbiddenError extends BuildError {\n constructor(message = \"Permission denied\") {\n super(message);\n this.name = \"ForbiddenError\";\n }\n}\n\nexport class TimeoutError extends BuildError {\n constructor(message = \"Operation timed out\") {\n super(message);\n this.name = \"TimeoutError\";\n }\n}\n\nexport class BadRequestError extends BuildError {\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"BadRequestError\";\n }\n}\n","/**\n * Build module entry point (verifiable builds + provenance)\n */\n\nimport { getEnvironmentConfig } from \"../../common/config/environment\";\nimport { withSDKTelemetry } from \"../../common/telemetry/wrapper\";\nimport { getLogger, addHexPrefix } from \"../../common/utils\";\nimport { BuildApiClient } from \"../../common/utils/buildapi\";\n\nimport { BUILD_STATUS } from \"./types\";\nimport type {\n Build,\n BuildProgress,\n BuildStatus,\n LogChunk,\n SubmitBuildRequest,\n SubmitBuildResponse,\n VerifyProvenanceResult,\n} from \"./types\";\nimport { AuthRequiredError, BuildFailedError, TimeoutError } from \"./errors\";\n\nexport interface BuildModuleConfig {\n privateKey?: string;\n environment?: string;\n verbose?: boolean;\n clientId?: string;\n skipTelemetry?: boolean;\n}\n\nexport interface BuildModule {\n submit(request: SubmitBuildRequest): Promise<SubmitBuildResponse>;\n getLogs(buildId: string): Promise<string>;\n\n list(options: { billingAddress: string; limit?: number; offset?: number }): Promise<Build[]>;\n get(buildId: string): Promise<Build>;\n getByDigest(digest: string): Promise<Build>;\n verify(identifier: string): Promise<VerifyProvenanceResult>;\n\n submitAndWait(\n request: SubmitBuildRequest,\n options?: {\n onLog?: (chunk: string) => void;\n onProgress?: (progress: BuildProgress) => void;\n pollIntervalMs?: number;\n timeoutMs?: number;\n },\n ): Promise<Build>;\n\n waitForBuild(\n buildId: string,\n options?: {\n onLog?: (chunk: string) => void;\n onProgress?: (progress: BuildProgress) => void;\n pollIntervalMs?: number;\n timeoutMs?: number;\n },\n ): Promise<Build>;\n\n streamLogs(buildId: string, pollIntervalMs?: number): AsyncGenerator<LogChunk, void, unknown>;\n}\n\nconst DEFAULT_POLL_INTERVAL = 2000;\nconst DEFAULT_TIMEOUT = 30 * 60 * 1000;\n\nexport function createBuildModule(config: BuildModuleConfig): BuildModule {\n const { verbose = false, skipTelemetry = false } = config;\n const logger = getLogger(verbose);\n\n const environment = config.environment || \"sepolia\";\n const environmentConfig = getEnvironmentConfig(environment);\n\n // NOTE: build endpoints are served from the compute UserAPI host\n const api = new BuildApiClient({\n baseUrl: environmentConfig.userApiServerURL,\n privateKey: config.privateKey ? addHexPrefix(config.privateKey) : undefined,\n clientId: config.clientId,\n });\n\n return {\n async submit(request: SubmitBuildRequest): Promise<SubmitBuildResponse> {\n return withSDKTelemetry(\n {\n functionName: \"build.submit\",\n skipTelemetry,\n properties: { environment, repoUrl: request.repoUrl },\n },\n async () => {\n if (!config.privateKey) throw new AuthRequiredError(\"Private key required for submit()\");\n\n const data = await api.submitBuild({\n repo_url: request.repoUrl,\n git_ref: request.gitRef,\n dockerfile_path: request.dockerfilePath ?? \"Dockerfile\",\n caddyfile_path: request.caddyfilePath,\n build_context_path: request.buildContextPath ?? \".\",\n dependencies: request.dependencies ?? [],\n });\n\n logger.debug(`Submitted build: ${data.build_id}`);\n return { buildId: data.build_id };\n },\n );\n },\n\n async list(options): Promise<Build[]> {\n const { billingAddress, limit, offset } = options;\n return withSDKTelemetry(\n {\n functionName: \"build.list\",\n skipTelemetry,\n properties: {\n environment,\n billingAddress,\n ...(limit !== undefined ? { limit: String(limit) } : {}),\n ...(offset !== undefined ? { offset: String(offset) } : {}),\n },\n },\n async () => {\n const data = await api.listBuilds({\n billing_address: billingAddress,\n limit,\n offset,\n });\n return Array.isArray(data) ? data.map(transformBuild) : [];\n },\n );\n },\n\n async get(buildId: string): Promise<Build> {\n return withSDKTelemetry(\n { functionName: \"build.get\", skipTelemetry, properties: { environment, buildId } },\n async () => transformBuild(await api.getBuild(buildId)),\n );\n },\n\n async getByDigest(digest: string): Promise<Build> {\n return withSDKTelemetry(\n { functionName: \"build.getByDigest\", skipTelemetry, properties: { environment, digest } },\n async () => transformBuild(await api.getBuildByDigest(digest)),\n );\n },\n\n async verify(identifier: string): Promise<VerifyProvenanceResult> {\n return withSDKTelemetry(\n { functionName: \"build.verify\", skipTelemetry, properties: { environment, identifier } },\n async () => transformVerifyResult(await api.verify(identifier)),\n );\n },\n\n async getLogs(buildId: string): Promise<string> {\n return withSDKTelemetry(\n { functionName: \"build.getLogs\", skipTelemetry, properties: { environment, buildId } },\n async () => {\n if (!config.privateKey) throw new AuthRequiredError(\"Private key required for getLogs()\");\n return api.getLogs(buildId);\n },\n );\n },\n\n async submitAndWait(request, options = {}) {\n const { buildId } = await this.submit(request);\n return this.waitForBuild(buildId, options);\n },\n\n async waitForBuild(buildId, options = {}) {\n const {\n onLog,\n onProgress,\n pollIntervalMs = DEFAULT_POLL_INTERVAL,\n timeoutMs = DEFAULT_TIMEOUT,\n } = options;\n\n const startTime = Date.now();\n let lastLogLength = 0;\n\n while (true) {\n if (Date.now() - startTime > timeoutMs) {\n throw new TimeoutError(`Build timed out after ${timeoutMs}ms`);\n }\n\n const build = await this.get(buildId);\n let logs = \"\";\n\n try {\n logs = await this.getLogs(buildId);\n if (onLog && logs.length > lastLogLength) {\n onLog(logs.slice(lastLogLength));\n lastLogLength = logs.length;\n }\n } catch {\n // ignore\n }\n\n onProgress?.({ build, logs });\n\n if (build.status === BUILD_STATUS.SUCCESS) return build;\n if (build.status === BUILD_STATUS.FAILED) {\n throw new BuildFailedError(build.errorMessage ?? \"Build failed\", buildId);\n }\n\n await sleep(pollIntervalMs);\n }\n },\n\n async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {\n let lastLength = 0;\n while (true) {\n const build = await this.get(buildId);\n let logs = \"\";\n\n try {\n logs = await this.getLogs(buildId);\n } catch {\n // ignore\n }\n\n if (logs.length > lastLength) {\n yield {\n content: logs.slice(lastLength),\n totalLength: logs.length,\n isComplete: build.status !== BUILD_STATUS.BUILDING,\n finalStatus: build.status !== BUILD_STATUS.BUILDING ? build.status : undefined,\n };\n lastLength = logs.length;\n }\n\n if (build.status !== BUILD_STATUS.BUILDING) break;\n await sleep(pollIntervalMs);\n }\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction transformBuild(raw: any): Build {\n return {\n buildId: raw.build_id,\n billingAddress: raw.billing_address,\n repoUrl: raw.repo_url,\n gitRef: raw.git_ref,\n status: raw.status as BuildStatus,\n buildType: raw.build_type,\n imageName: raw.image_name,\n imageUrl: raw.image_url,\n imageDigest: raw.image_digest,\n provenanceJson: raw.provenance_json ?? undefined,\n provenanceSignature: raw.provenance_signature ?? undefined,\n errorMessage: raw.error_message ?? undefined,\n createdAt: raw.created_at,\n updatedAt: raw.updated_at,\n dependencies: raw.dependencies\n ? Object.fromEntries(Object.entries(raw.dependencies).map(([k, v]) => [k, transformBuild(v)]))\n : undefined,\n };\n}\n\nfunction transformVerifyResult(raw: any): VerifyProvenanceResult {\n if (raw.status === \"verified\") {\n return {\n status: \"verified\",\n buildId: raw.build_id,\n imageUrl: raw.image_url,\n imageDigest: raw.image_digest,\n repoUrl: raw.repo_url,\n gitRef: raw.git_ref,\n provenanceJson: raw.provenance_json,\n provenanceSignature: raw.provenance_signature,\n payloadType: raw.payload_type,\n payload: raw.payload,\n };\n }\n\n return {\n status: \"failed\",\n error: raw.error,\n buildId: raw.build_id,\n };\n}\n\n// Re-export errors/types for convenience\nexport * from \"./types\";\nexport * from \"./errors\";\n","/**\n * Instance type utilities\n */\n\nimport { Address } from \"viem\";\nimport { PreflightContext } from \"./preflight\";\nimport { Logger } from \"../types\";\nimport { UserApiClient } from \"./userapi\";\n\n/**\n * Get current instance type for an app (best-effort)\n * Returns empty string if unable to fetch (API unavailable, app info not ready, etc.).\n * This is used as a convenience default for the upgrade flow.\n */\nexport async function getCurrentInstanceType(\n preflightCtx: PreflightContext,\n appID: Address,\n logger: Logger,\n clientId?: string,\n): Promise<string> {\n try {\n const userApiClient = new UserApiClient(\n preflightCtx.environmentConfig,\n preflightCtx.privateKey,\n preflightCtx.rpcUrl,\n clientId,\n );\n\n const infos = await userApiClient.getInfos([appID], 1);\n if (infos.length === 0) {\n return \"\"; // No app info available yet\n }\n\n return infos[0].machineType || \"\";\n } catch (err: any) {\n logger.debug(`Failed to get current instance type: ${err.message}`);\n return \"\"; // API call failed, skip default\n }\n}\n","/**\n * Main SDK Client entry point\n */\n\nimport { createComputeModule, type ComputeModule } from \"./modules/compute\";\nimport {\n getEnvironmentConfig,\n isEnvironmentAvailable,\n getAvailableEnvironments,\n} from \"./common/config/environment\";\nimport { createBillingModule, type BillingModule } from \"./modules/billing\";\nimport { createBuildModule, type BuildModule, type BuildModuleConfig } from \"./modules/build\";\nimport { addHexPrefix } from \"./common/utils\";\nimport { Hex } from \"viem\";\n\n// Export all types\nexport * from \"./common/types\";\n\n// Export validation utilities (non-interactive)\nexport * from \"./common/utils/validation\";\n\n// Export common hex helpers (used by CLI as well)\nexport { addHexPrefix, stripHexPrefix } from \"./common/utils\";\n\n// Special case on createApp - we don't need the client to run it\nexport {\n createApp,\n CreateAppOpts,\n SDKCreateAppOpts,\n PRIMARY_LANGUAGES,\n getAvailableTemplates,\n} from \"./modules/compute/app/create\";\nexport { logs, LogsOptions, SDKLogsOptions } from \"./modules/compute/app/logs\";\nexport {\n SDKDeployOptions,\n prepareDeploy,\n prepareDeployFromVerifiableBuild,\n executeDeploy,\n watchDeployment,\n type PrepareDeployResult,\n} from \"./modules/compute/app/deploy\";\nexport {\n SDKUpgradeOptions,\n prepareUpgrade,\n prepareUpgradeFromVerifiableBuild,\n executeUpgrade,\n watchUpgrade,\n type PrepareUpgradeResult,\n} from \"./modules/compute/app/upgrade\";\n\n// Export compute module for standalone use\nexport {\n createComputeModule,\n type ComputeModule,\n type ComputeModuleConfig,\n encodeStartAppData,\n encodeStopAppData,\n encodeTerminateAppData,\n} from \"./modules/compute\";\nexport {\n createBillingModule,\n type BillingModule,\n type BillingModuleConfig,\n} from \"./modules/billing\";\n\n// Export environment config utilities\nexport {\n getEnvironmentConfig,\n getAvailableEnvironments,\n isEnvironmentAvailable,\n getBuildType,\n isMainnet,\n} from \"./common/config/environment\";\nexport { isSubscriptionActive } from \"./common/utils/billing\";\n\n// Export auth utilities\nexport * from \"./common/auth\";\n\n// Export telemetry\nexport * from \"./common/telemetry\";\n\n// Export template catalog utilities for CLI\nexport {\n fetchTemplateCatalog,\n getTemplate,\n getCategoryDescriptions,\n} from \"./common/templates/catalog\";\n\n// Export contract utilities\nexport {\n getAllAppsByDeveloper,\n getAppLatestReleaseBlockNumbers,\n getBlockTimestamps,\n estimateTransactionGas,\n formatETH,\n type GasEstimate,\n type EstimateGasOptions,\n} from \"./common/contract/caller\";\n\n// Export batch gas estimation and delegation check\nexport {\n estimateBatchGas,\n checkERC7702Delegation,\n type EstimateBatchGasOptions,\n} from \"./common/contract/eip7702\";\n\n// Export instance type utilities\nexport { getCurrentInstanceType } from \"./common/utils/instance\";\n\n// Export user API client\nexport {\n UserApiClient,\n type AppInfo,\n type AppProfileInfo,\n type AppMetrics,\n type AppRelease,\n type AppReleaseBuild,\n type AppResponse,\n} from \"./common/utils/userapi\";\n\nexport type Environment = \"sepolia\" | \"sepolia-dev\" | \"mainnet-alpha\";\n\nexport interface ClientConfig {\n verbose: boolean;\n privateKey: Hex;\n environment: Environment | string;\n rpcUrl?: string;\n}\n\nexport interface ECloudClient {\n compute: ComputeModule;\n billing: BillingModule;\n}\n\nexport function createECloudClient(cfg: ClientConfig): ECloudClient {\n cfg.privateKey = addHexPrefix(cfg.privateKey);\n\n // Validate environment is available in current build\n const environment = cfg.environment || \"sepolia\";\n if (!isEnvironmentAvailable(environment)) {\n throw new Error(\n `Environment \"${environment}\" is not available in this build type. ` +\n `Available environments: ${getAvailableEnvironments().join(\", \")}`,\n );\n }\n\n // Get environment config\n const environmentConfig = getEnvironmentConfig(environment);\n\n // Get rpc url from environment config or use provided rpc url\n let rpcUrl = cfg.rpcUrl;\n if (!rpcUrl) {\n rpcUrl = process.env.RPC_URL ?? environmentConfig.defaultRPCURL;\n }\n if (!rpcUrl) {\n throw new Error(\n `RPC URL is required. Provide via options.rpcUrl, RPC_URL env var, or ensure environment has default RPC URL`,\n );\n }\n\n return {\n compute: createComputeModule({\n rpcUrl,\n verbose: cfg.verbose,\n privateKey: cfg.privateKey,\n environment: cfg.environment,\n }),\n billing: createBillingModule({\n verbose: cfg.verbose,\n privateKey: cfg.privateKey,\n }),\n };\n}\n\n// ============ Build module exports ============\nexport { createBuildModule };\nexport type { BuildModule, BuildModuleConfig };\nexport * from \"./modules/build/types\";\nexport * from \"./modules/build/errors\";\n"],"mappings":"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","names":["logs"]}
|