@phala/cloud 0.1.1-beta.3 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -32,7 +32,9 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AddComposeHashSchema: () => AddComposeHashSchema,
34
34
  ApiErrorSchema: () => ApiErrorSchema,
35
+ AuthError: () => AuthError,
35
36
  AvailableNodesSchema: () => AvailableNodesSchema,
37
+ BusinessError: () => BusinessError,
36
38
  CommitCvmComposeFileUpdateRequestSchema: () => CommitCvmComposeFileUpdateRequestSchema,
37
39
  CommitCvmComposeFileUpdateSchema: () => CommitCvmComposeFileUpdateSchema,
38
40
  CommitCvmProvisionRequestSchema: () => CommitCvmProvisionRequestSchema,
@@ -74,6 +76,7 @@ __export(index_exports, {
74
76
  NetworkError: () => NetworkError,
75
77
  PaginatedInstanceTypesSchema: () => PaginatedInstanceTypesSchema,
76
78
  PaginationMetadataSchema: () => PaginationMetadataSchema,
79
+ PhalaCloudError: () => PhalaCloudError,
77
80
  ProvisionCvmComposeFileUpdateRequestSchema: () => ProvisionCvmComposeFileUpdateRequestSchema,
78
81
  ProvisionCvmComposeFileUpdateResultSchema: () => ProvisionCvmComposeFileUpdateResultSchema,
79
82
  ProvisionCvmRequestSchema: () => ProvisionCvmRequestSchema,
@@ -81,13 +84,16 @@ __export(index_exports, {
81
84
  RequestError: () => RequestError,
82
85
  RestartCvmRequestSchema: () => RestartCvmRequestSchema,
83
86
  SUPPORTED_CHAINS: () => SUPPORTED_CHAINS,
87
+ ServerError: () => ServerError,
84
88
  ShutdownCvmRequestSchema: () => ShutdownCvmRequestSchema,
85
89
  StartCvmRequestSchema: () => StartCvmRequestSchema,
86
90
  StopCvmRequestSchema: () => StopCvmRequestSchema,
87
91
  TransactionError: () => TransactionError,
92
+ UnknownError: () => UnknownError,
88
93
  UpdateCvmResourcesRequestSchema: () => UpdateCvmResourcesRequestSchema,
89
94
  UpdateCvmVisibilityRequestSchema: () => UpdateCvmVisibilityRequestSchema,
90
95
  VMSchema: () => VMSchema,
96
+ ValidationError: () => ValidationError,
91
97
  VmInfoSchema: () => VmInfoSchema,
92
98
  WalletError: () => WalletError,
93
99
  WorkspaceResponseSchema: () => WorkspaceResponseSchema,
@@ -109,15 +115,18 @@ __export(index_exports, {
109
115
  defineSimpleAction: () => defineSimpleAction,
110
116
  deleteCvm: () => deleteCvm,
111
117
  deployAppAuth: () => deployAppAuth,
118
+ dumpAppCompose: () => dumpAppCompose,
112
119
  encryptEnvVars: () => import_encrypt_env_vars2.encryptEnvVars,
113
120
  estimateTransactionGas: () => estimateTransactionGas,
114
121
  executeBatchTransactions: () => executeBatchTransactions,
115
122
  executeTransaction: () => executeTransaction,
116
123
  executeTransactionWithRetry: () => executeTransactionWithRetry,
117
124
  extractNetworkClients: () => extractNetworkClients,
125
+ formatErrorMessage: () => formatErrorMessage,
126
+ formatValidationErrors: () => formatValidationErrors,
118
127
  getAppEnvEncryptPubKey: () => getAppEnvEncryptPubKey,
119
128
  getAvailableNodes: () => getAvailableNodes,
120
- getComposeHash: () => import_get_compose_hash2.getComposeHash,
129
+ getComposeHash: () => import_get_compose_hash3.getComposeHash,
121
130
  getCurrentUser: () => getCurrentUser,
122
131
  getCvmAttestation: () => getCvmAttestation,
123
132
  getCvmComposeFile: () => getCvmComposeFile,
@@ -130,11 +139,14 @@ __export(index_exports, {
130
139
  getErrorMessage: () => getErrorMessage,
131
140
  getKmsInfo: () => getKmsInfo,
132
141
  getKmsList: () => getKmsList,
142
+ getValidationFields: () => getValidationFields,
133
143
  getWorkspace: () => getWorkspace,
134
144
  listInstanceTypes: () => listInstanceTypes,
135
145
  listWorkspaces: () => listWorkspaces,
146
+ parseApiError: () => parseApiError,
136
147
  parseEnv: () => parseEnv,
137
148
  parseEnvVars: () => parseEnvVars,
149
+ preprocessAppCompose: () => preprocessAppCompose,
138
150
  provisionCvm: () => provisionCvm,
139
151
  provisionCvmComposeFileUpdate: () => provisionCvmComposeFileUpdate,
140
152
  refineCvmId: () => refineCvmId,
@@ -170,6 +182,7 @@ __export(index_exports, {
170
182
  safeUpdateCvmVisibility: () => safeUpdateCvmVisibility,
171
183
  safeValidateActionParameters: () => safeValidateActionParameters,
172
184
  shutdownCvm: () => shutdownCvm,
185
+ sortObject: () => sortObject,
173
186
  startCvm: () => startCvm,
174
187
  stopCvm: () => stopCvm,
175
188
  switchToNetwork: () => switchToNetwork,
@@ -178,15 +191,17 @@ __export(index_exports, {
178
191
  validateActionParameters: () => validateActionParameters,
179
192
  validateNetworkPrerequisites: () => validateNetworkPrerequisites,
180
193
  verifyEnvEncryptPublicKey: () => import_verify_env_encrypt_public_key.verifyEnvEncryptPublicKey,
181
- waitForTransactionReceipt: () => waitForTransactionReceipt
194
+ waitForTransactionReceipt: () => waitForTransactionReceipt,
195
+ withComposeMethods: () => withComposeMethods
182
196
  });
183
197
  module.exports = __toCommonJS(index_exports);
184
198
 
185
199
  // src/client.ts
186
200
  var import_ofetch = require("ofetch");
187
201
  var import_debug = __toESM(require("debug"));
202
+ var import_mitt = __toESM(require("mitt"));
188
203
 
189
- // src/types/client.ts
204
+ // src/utils/errors.ts
190
205
  var import_zod = require("zod");
191
206
  var ApiErrorSchema = import_zod.z.object({
192
207
  detail: import_zod.z.union([
@@ -199,21 +214,34 @@ var ApiErrorSchema = import_zod.z.object({
199
214
  })
200
215
  ),
201
216
  import_zod.z.record(import_zod.z.unknown())
202
- ]),
217
+ ]).optional(),
203
218
  type: import_zod.z.string().optional(),
204
219
  code: import_zod.z.string().optional()
205
220
  });
206
- var RequestError = class _RequestError extends Error {
207
- constructor(message, options) {
221
+ var PhalaCloudError = class extends Error {
222
+ constructor(message, data) {
208
223
  super(message);
224
+ this.name = this.constructor.name;
225
+ this.status = data.status;
226
+ this.statusText = data.statusText;
227
+ this.detail = data.detail;
228
+ if (Error.captureStackTrace) {
229
+ Error.captureStackTrace(this, this.constructor);
230
+ }
231
+ }
232
+ };
233
+ var RequestError = class _RequestError extends PhalaCloudError {
234
+ constructor(message, options) {
235
+ super(message, {
236
+ status: options?.status ?? 0,
237
+ statusText: options?.statusText ?? "Unknown Error",
238
+ detail: options?.detail || message
239
+ });
209
240
  this.name = "RequestError";
210
241
  this.isRequestError = true;
211
- this.status = options?.status;
212
- this.statusText = options?.statusText;
213
242
  this.data = options?.data;
214
243
  this.request = options?.request;
215
244
  this.response = options?.response;
216
- this.detail = options?.detail || message;
217
245
  this.code = options?.code;
218
246
  this.type = options?.type;
219
247
  }
@@ -254,9 +282,172 @@ var RequestError = class _RequestError extends Error {
254
282
  });
255
283
  }
256
284
  };
285
+ var ValidationError = class extends PhalaCloudError {
286
+ constructor(message, data) {
287
+ super(message, data);
288
+ this.isValidationError = true;
289
+ this.validationErrors = data.validationErrors;
290
+ }
291
+ };
292
+ var AuthError = class extends PhalaCloudError {
293
+ constructor() {
294
+ super(...arguments);
295
+ this.isAuthError = true;
296
+ }
297
+ };
298
+ var BusinessError = class extends PhalaCloudError {
299
+ constructor() {
300
+ super(...arguments);
301
+ this.isBusinessError = true;
302
+ }
303
+ };
304
+ var ServerError = class extends PhalaCloudError {
305
+ constructor() {
306
+ super(...arguments);
307
+ this.isServerError = true;
308
+ }
309
+ };
310
+ var UnknownError = class extends PhalaCloudError {
311
+ constructor() {
312
+ super(...arguments);
313
+ this.isUnknownError = true;
314
+ }
315
+ };
316
+ function extractFieldPath(loc) {
317
+ const filtered = loc.filter((part) => {
318
+ if (typeof part === "string") {
319
+ return !["body", "query", "path", "header"].includes(part);
320
+ }
321
+ return true;
322
+ });
323
+ return filtered.length > 0 ? filtered.join(".") : "unknown";
324
+ }
325
+ function parseValidationErrors(detail) {
326
+ if (!Array.isArray(detail)) {
327
+ return {
328
+ errors: [],
329
+ message: typeof detail === "string" ? detail : "Validation error"
330
+ };
331
+ }
332
+ const errors = detail.map((item) => ({
333
+ field: extractFieldPath(item.loc),
334
+ message: item.msg,
335
+ type: item.type,
336
+ context: item.ctx
337
+ }));
338
+ const count = errors.length;
339
+ const message = count === 1 ? `Validation failed: ${errors[0].message}` : `Validation failed (${count} issue${count > 1 ? "s" : ""})`;
340
+ return { errors, message };
341
+ }
342
+ function categorizeErrorType(status) {
343
+ if (status === 422) {
344
+ return "validation";
345
+ }
346
+ if (status === 401) {
347
+ return "auth";
348
+ }
349
+ if (status === 403) {
350
+ return "auth";
351
+ }
352
+ if (status >= 400 && status < 500) {
353
+ return "business";
354
+ }
355
+ if (status >= 500) {
356
+ return "server";
357
+ }
358
+ return "unknown";
359
+ }
360
+ function extractPrimaryMessage(status, detail, defaultMessage) {
361
+ if (status === 422 && Array.isArray(detail)) {
362
+ const { message } = parseValidationErrors(detail);
363
+ return message;
364
+ }
365
+ if (typeof detail === "string") {
366
+ return detail;
367
+ }
368
+ if (detail && typeof detail === "object" && "message" in detail) {
369
+ const msg = detail.message;
370
+ if (typeof msg === "string") {
371
+ return msg;
372
+ }
373
+ }
374
+ return defaultMessage;
375
+ }
376
+ function parseApiError(requestError) {
377
+ const status = requestError.status ?? 0;
378
+ const statusText = requestError.statusText ?? "Unknown Error";
379
+ const detail = requestError.detail;
380
+ const errorType = categorizeErrorType(status);
381
+ const message = extractPrimaryMessage(status, detail, requestError.message);
382
+ const commonData = {
383
+ status,
384
+ statusText,
385
+ detail
386
+ };
387
+ if (errorType === "validation" && Array.isArray(detail)) {
388
+ const { errors } = parseValidationErrors(detail);
389
+ return new ValidationError(message, {
390
+ ...commonData,
391
+ validationErrors: errors
392
+ });
393
+ }
394
+ if (errorType === "auth") {
395
+ return new AuthError(message, commonData);
396
+ }
397
+ if (errorType === "business") {
398
+ return new BusinessError(message, commonData);
399
+ }
400
+ if (errorType === "server") {
401
+ return new ServerError(message, commonData);
402
+ }
403
+ return new UnknownError(message, commonData);
404
+ }
405
+ function getValidationFields(error) {
406
+ if (error instanceof ValidationError) {
407
+ return error.validationErrors.map((e) => e.field);
408
+ }
409
+ return [];
410
+ }
411
+ function formatValidationErrors(errors, options) {
412
+ const { numbered = true, indent = 2, showFields = true } = options ?? {};
413
+ const indentStr = " ".repeat(indent);
414
+ return errors.map((error, index) => {
415
+ const prefix = numbered ? `${index + 1}. ` : "\u2022 ";
416
+ const field = showFields ? `${error.field}: ` : "";
417
+ return `${indentStr}${prefix}${field}${error.message}`;
418
+ }).join("\n");
419
+ }
420
+ function formatErrorMessage(error, options) {
421
+ const { showFields = true, showType = false } = options ?? {};
422
+ const parts = [];
423
+ if (showType) {
424
+ parts.push(`[${error.constructor.name.toUpperCase()}]`);
425
+ }
426
+ parts.push(error.message);
427
+ if (error instanceof ValidationError && error.validationErrors.length > 0) {
428
+ parts.push("");
429
+ parts.push(formatValidationErrors(error.validationErrors, { showFields }));
430
+ }
431
+ return parts.join("\n");
432
+ }
433
+ function getErrorMessage(error) {
434
+ if (typeof error.detail === "string") {
435
+ return error.detail;
436
+ }
437
+ if (Array.isArray(error.detail)) {
438
+ if (error.detail.length > 0) {
439
+ return error.detail[0]?.msg || "Validation error";
440
+ }
441
+ return "Validation error";
442
+ }
443
+ if (typeof error.detail === "object" && error.detail !== null) {
444
+ return JSON.stringify(error.detail);
445
+ }
446
+ return "Unknown error occurred";
447
+ }
257
448
 
258
449
  // src/client.ts
259
- var SUPPORTED_API_VERSIONS = ["2025-05-31"];
450
+ var SUPPORTED_API_VERSIONS = ["2025-05-31", "2025-10-28"];
260
451
  var logger = (0, import_debug.default)("phala::api-client");
261
452
  function formatHeaders(headers) {
262
453
  return Object.entries(headers).map(([key, value]) => ` -H "${key}: ${value}"`).join("\n");
@@ -282,18 +473,14 @@ function formatResponse(status, statusText, headers, body) {
282
473
  }
283
474
  var Client = class {
284
475
  constructor(config = {}) {
476
+ this.emitter = (0, import_mitt.default)();
285
477
  const resolvedConfig = {
286
478
  ...config,
287
479
  apiKey: config.apiKey || process?.env?.PHALA_CLOUD_API_KEY,
288
480
  baseURL: config.baseURL || process?.env?.PHALA_CLOUD_API_PREFIX || "https://cloud-api.phala.network/api/v1"
289
481
  };
290
- const version = resolvedConfig.version && SUPPORTED_API_VERSIONS.includes(resolvedConfig.version) ? resolvedConfig.version : SUPPORTED_API_VERSIONS[0];
482
+ const version = resolvedConfig.version && SUPPORTED_API_VERSIONS.includes(resolvedConfig.version) ? resolvedConfig.version : SUPPORTED_API_VERSIONS[SUPPORTED_API_VERSIONS.length - 1];
291
483
  this.config = resolvedConfig;
292
- if (!resolvedConfig.useCookieAuth && !resolvedConfig.apiKey) {
293
- throw new Error(
294
- "API key is required. Provide it via config.apiKey or set PHALA_CLOUD_API_KEY environment variable."
295
- );
296
- }
297
484
  const { apiKey, baseURL, timeout, headers, useCookieAuth, onResponseError, ...fetchOptions } = resolvedConfig;
298
485
  const requestHeaders = {
299
486
  "X-Phala-Version": version,
@@ -376,75 +563,137 @@ var Client = class {
376
563
  get raw() {
377
564
  return this.fetchInstance;
378
565
  }
566
+ on(type, handler) {
567
+ this.emitter.on(type, handler);
568
+ }
569
+ off(type, handler) {
570
+ this.emitter.off(type, handler);
571
+ }
572
+ once(type, handler) {
573
+ const wrappedHandler = (event) => {
574
+ handler(event);
575
+ this.emitter.off(type, wrappedHandler);
576
+ };
577
+ this.emitter.on(type, wrappedHandler);
578
+ }
379
579
  // ===== Direct methods (throw on error) =====
380
580
  /**
381
- * Perform GET request (throws on error)
581
+ * Perform GET request (throws PhalaCloudError on error)
382
582
  */
383
583
  async get(request, options) {
384
- return this.fetchInstance(request, {
385
- ...options,
386
- method: "GET"
387
- });
584
+ try {
585
+ return await this.fetchInstance(request, {
586
+ ...options,
587
+ method: "GET"
588
+ });
589
+ } catch (error) {
590
+ const requestError = this.convertToRequestError(error);
591
+ const phalaCloudError = this.emitError(requestError);
592
+ throw phalaCloudError;
593
+ }
388
594
  }
389
595
  /**
390
- * Perform POST request (throws on error)
596
+ * Perform POST request (throws PhalaCloudError on error)
391
597
  */
392
598
  async post(request, body, options) {
393
- return this.fetchInstance(request, {
394
- ...options,
395
- method: "POST",
396
- body
397
- });
599
+ try {
600
+ return await this.fetchInstance(request, {
601
+ ...options,
602
+ method: "POST",
603
+ body
604
+ });
605
+ } catch (error) {
606
+ const requestError = this.convertToRequestError(error);
607
+ const phalaCloudError = this.emitError(requestError);
608
+ throw phalaCloudError;
609
+ }
398
610
  }
399
611
  /**
400
- * Perform PUT request (throws on error)
612
+ * Perform PUT request (throws PhalaCloudError on error)
401
613
  */
402
614
  async put(request, body, options) {
403
- return this.fetchInstance(request, {
404
- ...options,
405
- method: "PUT",
406
- body
407
- });
615
+ try {
616
+ return await this.fetchInstance(request, {
617
+ ...options,
618
+ method: "PUT",
619
+ body
620
+ });
621
+ } catch (error) {
622
+ const requestError = this.convertToRequestError(error);
623
+ const phalaCloudError = this.emitError(requestError);
624
+ throw phalaCloudError;
625
+ }
408
626
  }
409
627
  /**
410
- * Perform PATCH request (throws on error)
628
+ * Perform PATCH request (throws PhalaCloudError on error)
411
629
  */
412
630
  async patch(request, body, options) {
413
- return this.fetchInstance(request, {
414
- ...options,
415
- method: "PATCH",
416
- body
417
- });
631
+ try {
632
+ return await this.fetchInstance(request, {
633
+ ...options,
634
+ method: "PATCH",
635
+ body
636
+ });
637
+ } catch (error) {
638
+ const requestError = this.convertToRequestError(error);
639
+ const phalaCloudError = this.emitError(requestError);
640
+ throw phalaCloudError;
641
+ }
418
642
  }
419
643
  /**
420
- * Perform DELETE request (throws on error)
644
+ * Perform DELETE request (throws PhalaCloudError on error)
421
645
  */
422
646
  async delete(request, options) {
423
- return this.fetchInstance(request, {
424
- ...options,
425
- method: "DELETE"
426
- });
647
+ try {
648
+ return await this.fetchInstance(request, {
649
+ ...options,
650
+ method: "DELETE"
651
+ });
652
+ } catch (error) {
653
+ const requestError = this.convertToRequestError(error);
654
+ const phalaCloudError = this.emitError(requestError);
655
+ throw phalaCloudError;
656
+ }
427
657
  }
428
658
  // ===== Safe methods (return SafeResult) =====
659
+ /**
660
+ * Convert any error to RequestError
661
+ */
662
+ convertToRequestError(error) {
663
+ if (error && typeof error === "object" && "data" in error) {
664
+ return RequestError.fromFetchError(error);
665
+ }
666
+ if (error instanceof Error) {
667
+ return RequestError.fromError(error);
668
+ }
669
+ return new RequestError("Unknown error occurred", {
670
+ detail: "Unknown error occurred"
671
+ });
672
+ }
673
+ /**
674
+ * Broadcast error to event listeners (fire-and-forget)
675
+ * @param requestError - The request error to handle
676
+ * @returns PhalaCloudError instance to throw immediately
677
+ */
678
+ emitError(requestError) {
679
+ const phalaCloudError = parseApiError(requestError);
680
+ this.emitter.emit("error", phalaCloudError);
681
+ return phalaCloudError;
682
+ }
429
683
  /**
430
684
  * Safe wrapper for any request method (zod-style result)
685
+ * Returns PhalaCloudError (all errors extend this base class)
431
686
  */
432
687
  async safeRequest(fn) {
433
688
  try {
434
689
  const data = await fn();
435
690
  return { success: true, data };
436
691
  } catch (error) {
437
- if (error && typeof error === "object" && "data" in error) {
438
- const requestError2 = RequestError.fromFetchError(error);
439
- return { success: false, error: requestError2 };
440
- }
441
- if (error instanceof Error) {
442
- const requestError2 = RequestError.fromError(error);
443
- return { success: false, error: requestError2 };
692
+ if (error instanceof PhalaCloudError) {
693
+ return { success: false, error };
444
694
  }
445
- const requestError = new RequestError("Unknown error occurred", {
446
- detail: "Unknown error occurred"
447
- });
695
+ const requestError = this.convertToRequestError(error);
696
+ this.emitError(requestError);
448
697
  return { success: false, error: requestError };
449
698
  }
450
699
  }
@@ -567,7 +816,7 @@ function defineSimpleAction(schema, fn) {
567
816
  const data = await fn(client);
568
817
  return { success: true, data };
569
818
  } catch (error) {
570
- if (error && typeof error === "object" && "isRequestError" in error) {
819
+ if (error && typeof error === "object" && "status" in error) {
571
820
  return { success: false, error };
572
821
  }
573
822
  if (error && typeof error === "object" && "issues" in error) {
@@ -624,7 +873,7 @@ function defineAction(schema, fn) {
624
873
  const data = await fn(client, params);
625
874
  return { success: true, data };
626
875
  } catch (error) {
627
- if (error && typeof error === "object" && "isRequestError" in error) {
876
+ if (error && typeof error === "object" && "status" in error) {
628
877
  return { success: false, error };
629
878
  }
630
879
  if (error && typeof error === "object" && "issues" in error) {
@@ -1039,18 +1288,6 @@ var ProvisionCvmRequestSchema = import_zod10.z.object({
1039
1288
  kms_id: import_zod10.z.string().optional(),
1040
1289
  env_keys: import_zod10.z.array(import_zod10.z.string()).optional()
1041
1290
  }).passthrough();
1042
- function autofillComposeFileName(appCompose) {
1043
- if (appCompose.compose_file && !appCompose.compose_file.name) {
1044
- return {
1045
- ...appCompose,
1046
- compose_file: {
1047
- ...appCompose.compose_file,
1048
- name: appCompose.name
1049
- }
1050
- };
1051
- }
1052
- return appCompose;
1053
- }
1054
1291
  function handleGatewayCompatibility(appCompose) {
1055
1292
  if (!appCompose.compose_file) {
1056
1293
  return appCompose;
@@ -1073,7 +1310,7 @@ function handleGatewayCompatibility(appCompose) {
1073
1310
  };
1074
1311
  }
1075
1312
  var { action: provisionCvm, safeAction: safeProvisionCvm } = defineAction(ProvisionCvmSchema, async (client, appCompose) => {
1076
- const body = handleGatewayCompatibility(autofillComposeFileName(appCompose));
1313
+ const body = handleGatewayCompatibility(appCompose);
1077
1314
  let requestBody = { ...body };
1078
1315
  if (typeof body.node_id === "number") {
1079
1316
  requestBody = { ...body, teepod_id: body.node_id };
@@ -1144,9 +1381,61 @@ var LooseAppComposeSchema = import_zod12.z.object({
1144
1381
  salt: import_zod12.z.string().optional().nullable()
1145
1382
  }).passthrough();
1146
1383
 
1384
+ // src/utils/get_compose_hash.ts
1385
+ var import_crypto = __toESM(require("crypto"));
1386
+ function sortObject(obj) {
1387
+ if (obj === void 0 || obj === null) {
1388
+ return obj;
1389
+ }
1390
+ if (Array.isArray(obj)) {
1391
+ return obj.map(sortObject);
1392
+ } else if (obj && typeof obj === "object" && obj.constructor === Object) {
1393
+ return Object.keys(obj).sort().reduce((result, key) => {
1394
+ const value = obj[key];
1395
+ result[key] = sortObject(value);
1396
+ return result;
1397
+ }, {});
1398
+ }
1399
+ return obj;
1400
+ }
1401
+ function preprocessAppCompose(dic) {
1402
+ const obj = { ...dic };
1403
+ if (obj.runner === "bash" && "docker_compose_file" in obj) {
1404
+ delete obj.docker_compose_file;
1405
+ } else if (obj.runner === "docker-compose" && "bash_script" in obj) {
1406
+ delete obj.bash_script;
1407
+ }
1408
+ if ("pre_launch_script" in obj && !obj.pre_launch_script) {
1409
+ delete obj.pre_launch_script;
1410
+ }
1411
+ return obj;
1412
+ }
1413
+ function dumpAppCompose(dic) {
1414
+ const ordered = sortObject(dic);
1415
+ let json = JSON.stringify(ordered, null, 4);
1416
+ json = json.replace(/": /g, '":');
1417
+ return json;
1418
+ }
1419
+ function getComposeHash(app_compose) {
1420
+ const preprocessed = preprocessAppCompose(app_compose);
1421
+ const manifest_str = dumpAppCompose(preprocessed);
1422
+ return import_crypto.default.createHash("sha256").update(manifest_str, "utf8").digest("hex");
1423
+ }
1424
+ function withComposeMethods(compose) {
1425
+ const appCompose = compose;
1426
+ return {
1427
+ ...compose,
1428
+ getHash: () => getComposeHash(appCompose),
1429
+ toString: () => dumpAppCompose(preprocessAppCompose(appCompose))
1430
+ };
1431
+ }
1432
+
1147
1433
  // src/actions/cvms/get_cvm_compose_file.ts
1434
+ var GetCvmComposeFileResultSchema = LooseAppComposeSchema.transform(
1435
+ (data) => withComposeMethods(data)
1436
+ );
1148
1437
  var GetCvmComposeFileRequestSchema = CvmIdSchema;
1149
- var { action: getCvmComposeFile, safeAction: safeGetCvmComposeFile } = defineAction(LooseAppComposeSchema, async (client, request) => {
1438
+ var { action: getCvmComposeFile, safeAction: safeGetCvmComposeFile } = defineAction(GetCvmComposeFileResultSchema, async (client, request) => {
1150
1439
  const { cvmId } = GetCvmComposeFileRequestSchema.parse(request);
1151
1440
  return await client.get(`/cvms/${cvmId}/compose_file`);
1152
1441
  });
@@ -1169,12 +1458,13 @@ var ProvisionCvmComposeFileUpdateRequestSchema = import_zod13.z.object({
1169
1458
  }).refine(
1170
1459
  (data) => !!(data.id || data.uuid || data.app_id || data.instance_id),
1171
1460
  "One of id, uuid, app_id, or instance_id must be provided"
1172
- ).transform((data) => ({
1173
- cvmId: data.id || data.uuid || data.app_id || data.instance_id,
1174
- request: data.app_compose,
1175
- update_env_vars: data.update_env_vars,
1176
- _raw: data
1177
- }));
1461
+ ).transform((data) => {
1462
+ return {
1463
+ cvmId: data.id || data.uuid || data.app_id || data.instance_id,
1464
+ request: { ...data.app_compose, update_env_vars: data.update_env_vars },
1465
+ _raw: data
1466
+ };
1467
+ });
1178
1468
  var ProvisionCvmComposeFileUpdateResultSchema = import_zod13.z.object({
1179
1469
  app_id: import_zod13.z.string().nullable(),
1180
1470
  device_id: import_zod13.z.string().nullable(),
@@ -1596,23 +1886,6 @@ var import_accounts2 = require("viem/accounts");
1596
1886
  // src/utils/index.ts
1597
1887
  var import_encrypt_env_vars = require("@phala/dstack-sdk/encrypt-env-vars");
1598
1888
 
1599
- // src/utils/get_error_message.ts
1600
- function getErrorMessage(error) {
1601
- if (typeof error.detail === "string") {
1602
- return error.detail;
1603
- }
1604
- if (Array.isArray(error.detail)) {
1605
- if (error.detail.length > 0) {
1606
- return error.detail[0]?.msg || "Validation error";
1607
- }
1608
- return "Validation error";
1609
- }
1610
- if (typeof error.detail === "object" && error.detail !== null) {
1611
- return JSON.stringify(error.detail);
1612
- }
1613
- return "Unknown error occurred";
1614
- }
1615
-
1616
1889
  // src/utils/as-hex.ts
1617
1890
  var import_viem = require("viem");
1618
1891
  function asHex(value) {
@@ -2847,13 +3120,15 @@ function parseEnvVars(input) {
2847
3120
 
2848
3121
  // src/index.ts
2849
3122
  var import_encrypt_env_vars2 = require("@phala/dstack-sdk/encrypt-env-vars");
2850
- var import_get_compose_hash2 = require("@phala/dstack-sdk/get-compose-hash");
3123
+ var import_get_compose_hash3 = require("@phala/dstack-sdk/get-compose-hash");
2851
3124
  var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env-encrypt-public-key");
2852
3125
  // Annotate the CommonJS export names for ESM import in node:
2853
3126
  0 && (module.exports = {
2854
3127
  AddComposeHashSchema,
2855
3128
  ApiErrorSchema,
3129
+ AuthError,
2856
3130
  AvailableNodesSchema,
3131
+ BusinessError,
2857
3132
  CommitCvmComposeFileUpdateRequestSchema,
2858
3133
  CommitCvmComposeFileUpdateSchema,
2859
3134
  CommitCvmProvisionRequestSchema,
@@ -2895,6 +3170,7 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2895
3170
  NetworkError,
2896
3171
  PaginatedInstanceTypesSchema,
2897
3172
  PaginationMetadataSchema,
3173
+ PhalaCloudError,
2898
3174
  ProvisionCvmComposeFileUpdateRequestSchema,
2899
3175
  ProvisionCvmComposeFileUpdateResultSchema,
2900
3176
  ProvisionCvmRequestSchema,
@@ -2902,13 +3178,16 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2902
3178
  RequestError,
2903
3179
  RestartCvmRequestSchema,
2904
3180
  SUPPORTED_CHAINS,
3181
+ ServerError,
2905
3182
  ShutdownCvmRequestSchema,
2906
3183
  StartCvmRequestSchema,
2907
3184
  StopCvmRequestSchema,
2908
3185
  TransactionError,
3186
+ UnknownError,
2909
3187
  UpdateCvmResourcesRequestSchema,
2910
3188
  UpdateCvmVisibilityRequestSchema,
2911
3189
  VMSchema,
3190
+ ValidationError,
2912
3191
  VmInfoSchema,
2913
3192
  WalletError,
2914
3193
  WorkspaceResponseSchema,
@@ -2930,12 +3209,15 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2930
3209
  defineSimpleAction,
2931
3210
  deleteCvm,
2932
3211
  deployAppAuth,
3212
+ dumpAppCompose,
2933
3213
  encryptEnvVars,
2934
3214
  estimateTransactionGas,
2935
3215
  executeBatchTransactions,
2936
3216
  executeTransaction,
2937
3217
  executeTransactionWithRetry,
2938
3218
  extractNetworkClients,
3219
+ formatErrorMessage,
3220
+ formatValidationErrors,
2939
3221
  getAppEnvEncryptPubKey,
2940
3222
  getAvailableNodes,
2941
3223
  getComposeHash,
@@ -2951,11 +3233,14 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2951
3233
  getErrorMessage,
2952
3234
  getKmsInfo,
2953
3235
  getKmsList,
3236
+ getValidationFields,
2954
3237
  getWorkspace,
2955
3238
  listInstanceTypes,
2956
3239
  listWorkspaces,
3240
+ parseApiError,
2957
3241
  parseEnv,
2958
3242
  parseEnvVars,
3243
+ preprocessAppCompose,
2959
3244
  provisionCvm,
2960
3245
  provisionCvmComposeFileUpdate,
2961
3246
  refineCvmId,
@@ -2991,6 +3276,7 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2991
3276
  safeUpdateCvmVisibility,
2992
3277
  safeValidateActionParameters,
2993
3278
  shutdownCvm,
3279
+ sortObject,
2994
3280
  startCvm,
2995
3281
  stopCvm,
2996
3282
  switchToNetwork,
@@ -2999,5 +3285,6 @@ var import_verify_env_encrypt_public_key = require("@phala/dstack-sdk/verify-env
2999
3285
  validateActionParameters,
3000
3286
  validateNetworkPrerequisites,
3001
3287
  verifyEnvEncryptPublicKey,
3002
- waitForTransactionReceipt
3288
+ waitForTransactionReceipt,
3289
+ withComposeMethods
3003
3290
  });