modal 0.5.0 → 0.5.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
@@ -43635,6 +43635,15 @@ var FunctionService = class {
43635
43635
  objectTag: name,
43636
43636
  environmentName: this.#client.environmentName(params.environment)
43637
43637
  });
43638
+ this.#client.logger.debug(
43639
+ "Retrieved Function",
43640
+ "function_id",
43641
+ resp.functionId,
43642
+ "app_name",
43643
+ appName,
43644
+ "function_name",
43645
+ name
43646
+ );
43638
43647
  return new Function_(
43639
43648
  this.#client,
43640
43649
  resp.functionId,
@@ -43666,16 +43675,42 @@ var Function_ = class {
43666
43675
  static async lookup(appName, name, params = {}) {
43667
43676
  return await getDefaultClient().functions.fromName(appName, name, params);
43668
43677
  }
43678
+ #checkNoWebUrl(fnName) {
43679
+ if (this.#handleMetadata?.webUrl) {
43680
+ throw new InvalidError(
43681
+ `A webhook Function cannot be invoked for remote execution with '.${fnName}'. Invoke this Function via its web url '${this.#handleMetadata.webUrl}' instead.`
43682
+ );
43683
+ }
43684
+ }
43669
43685
  // Execute a single input into a remote Function.
43670
43686
  async remote(args = [], kwargs = {}) {
43687
+ this.#client.logger.debug(
43688
+ "Executing function call",
43689
+ "function_id",
43690
+ this.functionId
43691
+ );
43692
+ this.#checkNoWebUrl("remote");
43671
43693
  const input = await this.#createInput(args, kwargs);
43672
43694
  const invocation = await this.#createRemoteInvocation(input);
43673
43695
  let retryCount = 0;
43674
43696
  while (true) {
43675
43697
  try {
43676
- return await invocation.awaitOutput();
43698
+ const result = await invocation.awaitOutput();
43699
+ this.#client.logger.debug(
43700
+ "Function call completed",
43701
+ "function_id",
43702
+ this.functionId
43703
+ );
43704
+ return result;
43677
43705
  } catch (err) {
43678
43706
  if (err instanceof InternalFailure && retryCount <= maxSystemRetries) {
43707
+ this.#client.logger.debug(
43708
+ "Retrying function call due to internal failure",
43709
+ "function_id",
43710
+ this.functionId,
43711
+ "retry_count",
43712
+ retryCount
43713
+ );
43679
43714
  await invocation.retry(retryCount);
43680
43715
  retryCount++;
43681
43716
  } else {
@@ -43702,6 +43737,12 @@ var Function_ = class {
43702
43737
  }
43703
43738
  // Spawn a single input into a remote Function.
43704
43739
  async spawn(args = [], kwargs = {}) {
43740
+ this.#client.logger.debug(
43741
+ "Spawning function call",
43742
+ "function_id",
43743
+ this.functionId
43744
+ );
43745
+ this.#checkNoWebUrl("spawn");
43705
43746
  const input = await this.#createInput(args, kwargs);
43706
43747
  const invocation = await ControlPlaneInvocation.create(
43707
43748
  this.#client,
@@ -43709,6 +43750,13 @@ var Function_ = class {
43709
43750
  input,
43710
43751
  3 /* FUNCTION_CALL_INVOCATION_TYPE_ASYNC */
43711
43752
  );
43753
+ this.#client.logger.debug(
43754
+ "Function call spawned",
43755
+ "function_id",
43756
+ this.functionId,
43757
+ "function_call_id",
43758
+ invocation.functionCallId
43759
+ );
43712
43760
  return new FunctionCall(this.#client, invocation.functionCallId);
43713
43761
  }
43714
43762
  // Returns statistics about the Function.
@@ -43748,7 +43796,7 @@ var Function_ = class {
43748
43796
  const supported_input_formats = this.#handleMetadata?.supportedInputFormats?.length ? this.#handleMetadata.supportedInputFormats : [1 /* DATA_FORMAT_PICKLE */];
43749
43797
  if (!supported_input_formats.includes(4 /* DATA_FORMAT_CBOR */)) {
43750
43798
  throw new InvalidError(
43751
- "the deployed Function does not support libmodal - please redeploy it using Modal Python SDK version >= 1.2"
43799
+ "cannot call Modal Function from JS SDK since it was deployed with an incompatible Python SDK version. Redeploy with Modal Python SDK >= 1.2"
43752
43800
  );
43753
43801
  }
43754
43802
  const payload = cborEncode([args, kwargs]);
@@ -43811,6 +43859,13 @@ var SecretService = class {
43811
43859
  environmentName: this.#client.environmentName(params?.environment),
43812
43860
  requiredKeys: params?.requiredKeys ?? []
43813
43861
  });
43862
+ this.#client.logger.debug(
43863
+ "Retrieved Secret",
43864
+ "secret_id",
43865
+ resp.secretId,
43866
+ "secret_name",
43867
+ name
43868
+ );
43814
43869
  return new Secret(resp.secretId, name);
43815
43870
  } catch (err) {
43816
43871
  if (err instanceof ClientError2 && err.code === Status2.NOT_FOUND)
@@ -43835,6 +43890,11 @@ var SecretService = class {
43835
43890
  envDict: entries,
43836
43891
  environmentName: this.#client.environmentName(params?.environment)
43837
43892
  });
43893
+ this.#client.logger.debug(
43894
+ "Created ephemeral Secret",
43895
+ "secret_id",
43896
+ resp.secretId
43897
+ );
43838
43898
  return new Secret(resp.secretId);
43839
43899
  } catch (err) {
43840
43900
  if (err instanceof ClientError2 && (err.code === Status2.INVALID_ARGUMENT || err.code === Status2.FAILED_PRECONDITION))
@@ -43955,6 +44015,15 @@ var ClsService = class {
43955
44015
  `Unsupported parameter format: ${parameterInfo?.format}`
43956
44016
  );
43957
44017
  }
44018
+ this.#client.logger.debug(
44019
+ "Retrieved Cls",
44020
+ "function_id",
44021
+ serviceFunction.functionId,
44022
+ "app_name",
44023
+ appName,
44024
+ "cls_name",
44025
+ name
44026
+ );
43958
44027
  return new Cls(
43959
44028
  this.#client,
43960
44029
  serviceFunction.functionId,
@@ -44333,8 +44402,15 @@ var ImageService = class {
44333
44402
  * Delete an {@link Image} by ID. Warning: This removes an *entire Image*, and cannot be undone.
44334
44403
  */
44335
44404
  async delete(imageId, _ = {}) {
44336
- const image = await this.fromId(imageId);
44337
- await this.#client.cpClient.imageDelete({ imageId: image.imageId });
44405
+ try {
44406
+ await this.#client.cpClient.imageDelete({ imageId });
44407
+ } catch (err) {
44408
+ if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
44409
+ throw new NotFoundError(err.details);
44410
+ if (err instanceof ClientError4 && err.code === Status4.FAILED_PRECONDITION && err.details.includes("Could not find image with ID"))
44411
+ throw new NotFoundError(err.details);
44412
+ throw err;
44413
+ }
44338
44414
  }
44339
44415
  };
44340
44416
  var Image2 = class _Image {
@@ -44432,6 +44508,7 @@ var Image2 = class _Image {
44432
44508
  if (this.imageId !== "") {
44433
44509
  return this;
44434
44510
  }
44511
+ this.#client.logger.debug("Building image", "app_id", app.appId);
44435
44512
  let baseImageId;
44436
44513
  for (let i = 0; i < this.#layers.length; i++) {
44437
44514
  const layer = this.#layers[i];
@@ -44506,6 +44583,7 @@ ${result.exception}`
44506
44583
  baseImageId = resp.imageId;
44507
44584
  }
44508
44585
  this.#imageId = baseImageId;
44586
+ this.#client.logger.debug("Image build completed", "image_id", baseImageId);
44509
44587
  return this;
44510
44588
  }
44511
44589
  /**
@@ -44969,6 +45047,11 @@ var QueueService = class {
44969
45047
  objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
44970
45048
  environmentName: this.#client.environmentName(params.environment)
44971
45049
  });
45050
+ this.#client.logger.debug(
45051
+ "Created ephemeral Queue",
45052
+ "queue_id",
45053
+ resp.queueId
45054
+ );
44972
45055
  const ephemeralHbManager = new EphemeralHeartbeatManager(
44973
45056
  () => this.#client.cpClient.queueHeartbeat({ queueId: resp.queueId })
44974
45057
  );
@@ -44983,6 +45066,13 @@ var QueueService = class {
44983
45066
  objectCreationType: params.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : void 0,
44984
45067
  environmentName: this.#client.environmentName(params.environment)
44985
45068
  });
45069
+ this.#client.logger.debug(
45070
+ "Retrieved Queue",
45071
+ "queue_id",
45072
+ resp.queueId,
45073
+ "queue_name",
45074
+ name
45075
+ );
44986
45076
  return new Queue(this.#client, resp.queueId, name);
44987
45077
  }
44988
45078
  /**
@@ -45694,6 +45784,11 @@ var SandboxService = class {
45694
45784
  }
45695
45785
  throw err;
45696
45786
  }
45787
+ this.#client.logger.debug(
45788
+ "Created Sandbox",
45789
+ "sandbox_id",
45790
+ createResp.sandboxId
45791
+ );
45697
45792
  return new Sandbox2(this.#client, createResp.sandboxId);
45698
45793
  }
45699
45794
  /** Returns a running {@link Sandbox} object from an ID.
@@ -45954,6 +46049,15 @@ var Sandbox2 = class _Sandbox {
45954
46049
  mergedParams
45955
46050
  );
45956
46051
  const resp = await this.#client.cpClient.containerExec(req);
46052
+ this.#client.logger.debug(
46053
+ "Created ContainerProcess",
46054
+ "exec_id",
46055
+ resp.execId,
46056
+ "sandbox_id",
46057
+ this.sandboxId,
46058
+ "command",
46059
+ command
46060
+ );
45957
46061
  return new ContainerProcess(this.#client, resp.execId, params);
45958
46062
  }
45959
46063
  async #getTaskId() {
@@ -45986,7 +46090,17 @@ var Sandbox2 = class _Sandbox {
45986
46090
  timeout: 10
45987
46091
  });
45988
46092
  if (resp.result) {
45989
- return _Sandbox.#getReturnCode(resp.result);
46093
+ const returnCode = _Sandbox.#getReturnCode(resp.result);
46094
+ this.#client.logger.debug(
46095
+ "Sandbox wait completed",
46096
+ "sandbox_id",
46097
+ this.sandboxId,
46098
+ "status",
46099
+ resp.result.status,
46100
+ "return_code",
46101
+ returnCode
46102
+ );
46103
+ return returnCode;
45990
46104
  }
45991
46105
  }
45992
46106
  }
@@ -46251,6 +46365,13 @@ var VolumeService = class {
46251
46365
  environmentName: this.#client.environmentName(params?.environment),
46252
46366
  objectCreationType: params?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
46253
46367
  });
46368
+ this.#client.logger.debug(
46369
+ "Retrieved Volume",
46370
+ "volume_id",
46371
+ resp.volumeId,
46372
+ "volume_name",
46373
+ name
46374
+ );
46254
46375
  return new Volume(resp.volumeId, name);
46255
46376
  } catch (err) {
46256
46377
  if (err instanceof ClientError8 && err.code === Status8.NOT_FOUND)
@@ -46267,6 +46388,11 @@ var VolumeService = class {
46267
46388
  objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
46268
46389
  environmentName: this.#client.environmentName(params.environment)
46269
46390
  });
46391
+ this.#client.logger.debug(
46392
+ "Created ephemeral Volume",
46393
+ "volume_id",
46394
+ resp.volumeId
46395
+ );
46270
46396
  const ephemeralHbManager = new EphemeralHeartbeatManager(
46271
46397
  () => this.#client.cpClient.volumeHeartbeat({ volumeId: resp.volumeId })
46272
46398
  );
@@ -46319,9 +46445,17 @@ import { readFileSync } from "node:fs";
46319
46445
  import { homedir } from "node:os";
46320
46446
  import path from "node:path";
46321
46447
  import { parse as parseToml } from "smol-toml";
46448
+ function configFilePath() {
46449
+ const configPath = process.env["MODAL_CONFIG_PATH"];
46450
+ if (configPath && configPath !== "") {
46451
+ return configPath;
46452
+ }
46453
+ return path.join(homedir(), ".modal.toml");
46454
+ }
46322
46455
  function readConfigFile() {
46323
46456
  try {
46324
- const configContent = readFileSync(path.join(homedir(), ".modal.toml"), {
46457
+ const configPath = configFilePath();
46458
+ const configContent = readFileSync(configPath, {
46325
46459
  encoding: "utf-8"
46326
46460
  });
46327
46461
  return parseToml(configContent);
@@ -46348,7 +46482,8 @@ function getProfile(profileName) {
46348
46482
  tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
46349
46483
  tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
46350
46484
  environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
46351
- imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion
46485
+ imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion,
46486
+ logLevel: process.env["MODAL_LOGLEVEL"] || profileData.loglevel
46352
46487
  };
46353
46488
  return profile;
46354
46489
  }
@@ -46358,13 +46493,15 @@ var REFRESH_WINDOW = 5 * 60;
46358
46493
  var DEFAULT_EXPIRY_OFFSET = 20 * 60;
46359
46494
  var AuthTokenManager = class {
46360
46495
  client;
46496
+ logger;
46361
46497
  currentToken = "";
46362
46498
  tokenExpiry = 0;
46363
46499
  stopped = false;
46364
46500
  timeoutId = null;
46365
46501
  initialTokenPromise = null;
46366
- constructor(client2) {
46502
+ constructor(client2, logger) {
46367
46503
  this.client = client2;
46504
+ this.logger = logger;
46368
46505
  }
46369
46506
  /**
46370
46507
  * Returns the current cached token.
@@ -46395,9 +46532,19 @@ var AuthTokenManager = class {
46395
46532
  if (exp > 0) {
46396
46533
  this.tokenExpiry = exp;
46397
46534
  } else {
46398
- console.warn("Failed to decode x-modal-auth-token exp field");
46535
+ this.logger.warn("x-modal-auth-token does not contain exp field");
46399
46536
  this.tokenExpiry = Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_OFFSET;
46400
46537
  }
46538
+ const now = Math.floor(Date.now() / 1e3);
46539
+ const expiresIn = this.tokenExpiry - now;
46540
+ const refreshIn = this.tokenExpiry - now - REFRESH_WINDOW;
46541
+ this.logger.debug(
46542
+ "Fetched auth token",
46543
+ "expires_in",
46544
+ `${expiresIn}s`,
46545
+ "refresh_in",
46546
+ `${refreshIn}s`
46547
+ );
46401
46548
  }
46402
46549
  /**
46403
46550
  * Background loop that refreshes tokens REFRESH_WINDOW seconds before they expire.
@@ -46417,7 +46564,7 @@ var AuthTokenManager = class {
46417
46564
  try {
46418
46565
  await this.fetchToken();
46419
46566
  } catch (error) {
46420
- console.error("Failed to refresh auth token:", error);
46567
+ this.logger.error("Failed to refresh auth token", "error", error);
46421
46568
  await new Promise((resolve) => setTimeout(resolve, 5e3));
46422
46569
  }
46423
46570
  }
@@ -46481,7 +46628,113 @@ var AuthTokenManager = class {
46481
46628
 
46482
46629
  // src/version.ts
46483
46630
  function getSDKVersion() {
46484
- return true ? "0.5.0" : "0.0.0";
46631
+ return true ? "0.5.2" : "0.0.0";
46632
+ }
46633
+
46634
+ // src/logger.ts
46635
+ var LOG_LEVELS = {
46636
+ debug: 0,
46637
+ info: 1,
46638
+ warn: 2,
46639
+ error: 3
46640
+ };
46641
+ function parseLogLevel(level) {
46642
+ if (!level) {
46643
+ return "warn";
46644
+ }
46645
+ const normalized = level.toLowerCase();
46646
+ if (normalized === "debug" || normalized === "info" || normalized === "warn" || normalized === "warning" || normalized === "error") {
46647
+ return normalized === "warning" ? "warn" : normalized;
46648
+ }
46649
+ throw new Error(
46650
+ `Invalid log level value: "${level}" (must be debug, info, warn, or error)`
46651
+ );
46652
+ }
46653
+ var DefaultLogger = class {
46654
+ levelValue;
46655
+ constructor(level = "warn") {
46656
+ this.levelValue = LOG_LEVELS[level];
46657
+ }
46658
+ debug(message, ...args) {
46659
+ if (this.levelValue <= LOG_LEVELS.debug) {
46660
+ console.log(this.formatMessage("DEBUG", message, args));
46661
+ }
46662
+ }
46663
+ info(message, ...args) {
46664
+ if (this.levelValue <= LOG_LEVELS.info) {
46665
+ console.log(this.formatMessage("INFO", message, args));
46666
+ }
46667
+ }
46668
+ warn(message, ...args) {
46669
+ if (this.levelValue <= LOG_LEVELS.warn) {
46670
+ console.warn(this.formatMessage("WARN", message, args));
46671
+ }
46672
+ }
46673
+ error(message, ...args) {
46674
+ if (this.levelValue <= LOG_LEVELS.error) {
46675
+ console.error(this.formatMessage("ERROR", message, args));
46676
+ }
46677
+ }
46678
+ formatMessage(level, message, args) {
46679
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
46680
+ let formatted = `time=${timestamp} level=${level} msg="${message}"`;
46681
+ if (args.length > 0) {
46682
+ for (let i = 0; i < args.length; i += 2) {
46683
+ if (i + 1 < args.length) {
46684
+ const key = args[i];
46685
+ const value = args[i + 1];
46686
+ formatted += ` ${key}=${this.formatValue(value)}`;
46687
+ }
46688
+ }
46689
+ }
46690
+ return formatted;
46691
+ }
46692
+ formatValue(value) {
46693
+ if (typeof value === "string") {
46694
+ return value.includes(" ") ? `"${value}"` : value;
46695
+ }
46696
+ if (value instanceof Error) {
46697
+ return `"${value.message}"`;
46698
+ }
46699
+ if (Array.isArray(value)) {
46700
+ return `[${value.join(",")}]`;
46701
+ }
46702
+ return String(value);
46703
+ }
46704
+ };
46705
+ var FilteredLogger = class {
46706
+ constructor(logger, level) {
46707
+ this.logger = logger;
46708
+ this.levelValue = LOG_LEVELS[level];
46709
+ }
46710
+ levelValue;
46711
+ debug(message, ...args) {
46712
+ if (this.levelValue <= LOG_LEVELS.debug) {
46713
+ this.logger.debug(message, ...args);
46714
+ }
46715
+ }
46716
+ info(message, ...args) {
46717
+ if (this.levelValue <= LOG_LEVELS.info) {
46718
+ this.logger.info(message, ...args);
46719
+ }
46720
+ }
46721
+ warn(message, ...args) {
46722
+ if (this.levelValue <= LOG_LEVELS.warn) {
46723
+ this.logger.warn(message, ...args);
46724
+ }
46725
+ }
46726
+ error(message, ...args) {
46727
+ if (this.levelValue <= LOG_LEVELS.error) {
46728
+ this.logger.error(message, ...args);
46729
+ }
46730
+ }
46731
+ };
46732
+ function createLogger(logger, logLevel = "") {
46733
+ const level = parseLogLevel(logLevel);
46734
+ if (logger) {
46735
+ return new FilteredLogger(logger, level);
46736
+ }
46737
+ return new DefaultLogger(level);
46485
46738
  }
46486
46739
 
46487
46740
  // src/client.ts
@@ -46499,8 +46752,10 @@ var ModalClient = class {
46499
46752
  /** @ignore */
46500
46753
  cpClient;
46501
46754
  profile;
46755
+ logger;
46502
46756
  ipClients;
46503
46757
  authTokenManager = null;
46758
+ customMiddleware;
46504
46759
  constructor(params) {
46505
46760
  checkForRenamedParams(params, { timeout: "timeoutMs" });
46506
46761
  const baseProfile = getProfile(process.env["MODAL_PROFILE"]);
@@ -46510,8 +46765,19 @@ var ModalClient = class {
46510
46765
  ...params?.tokenSecret && { tokenSecret: params.tokenSecret },
46511
46766
  ...params?.environment && { environment: params.environment }
46512
46767
  };
46768
+ const logLevelValue = params?.logLevel || this.profile.logLevel || "";
46769
+ this.logger = createLogger(params?.logger, logLevelValue);
46770
+ this.logger.debug(
46771
+ "Initializing Modal client",
46772
+ "version",
46773
+ getSDKVersion(),
46774
+ "server_url",
46775
+ this.profile.serverUrl
46776
+ );
46777
+ this.customMiddleware = params?.grpcMiddleware ?? [];
46513
46778
  this.ipClients = /* @__PURE__ */ new Map();
46514
46779
  this.cpClient = params?.cpClient ?? this.createClient(this.profile);
46780
+ this.logger.debug("Modal client initialized successfully");
46515
46781
  this.apps = new AppService(this);
46516
46782
  this.cls = new ClsService(this);
46517
46783
  this.functions = new FunctionService(this);
@@ -46535,16 +46801,19 @@ var ModalClient = class {
46535
46801
  if (existing) {
46536
46802
  return existing;
46537
46803
  }
46804
+ this.logger.debug("Creating input plane client", "server_url", serverUrl);
46538
46805
  const profile = { ...this.profile, serverUrl };
46539
46806
  const newClient = this.createClient(profile);
46540
46807
  this.ipClients.set(serverUrl, newClient);
46541
46808
  return newClient;
46542
46809
  }
46543
46810
  close() {
46811
+ this.logger.debug("Closing Modal client");
46544
46812
  if (this.authTokenManager) {
46545
46813
  this.authTokenManager.stop();
46546
46814
  this.authTokenManager = null;
46547
46815
  }
46816
+ this.logger.debug("Modal client closed");
46548
46817
  }
46549
46818
  version() {
46550
46819
  return getSDKVersion();
@@ -46555,12 +46824,101 @@ var ModalClient = class {
46555
46824
  "grpc.max_send_message_length": 100 * 1024 * 1024,
46556
46825
  "grpc-node.flow_control_window": 64 * 1024 * 1024
46557
46826
  });
46558
- return createClientFactory().use(this.authMiddleware(profile)).use(retryMiddleware).use(timeoutMiddleware).create(ModalClientDefinition, channel);
46827
+ let factory = createClientFactory().use(this.authMiddleware(profile)).use(this.retryMiddleware()).use(timeoutMiddleware);
46828
+ for (const middleware of this.customMiddleware) {
46829
+ factory = factory.use(middleware);
46830
+ }
46831
+ return factory.create(ModalClientDefinition, channel);
46832
+ }
46833
+ /** Middleware to retry transient errors and timeouts for unary requests. */
46834
+ retryMiddleware() {
46835
+ const logger = this.logger;
46836
+ return async function* retryMiddleware(call, options) {
46837
+ const {
46838
+ retries = 3,
46839
+ baseDelay = 100,
46840
+ maxDelay = 1e3,
46841
+ delayFactor = 2,
46842
+ additionalStatusCodes = [],
46843
+ signal,
46844
+ ...restOptions
46845
+ } = options;
46846
+ if (call.requestStream || call.responseStream || !retries) {
46847
+ return yield* call.next(call.request, restOptions);
46848
+ }
46849
+ const retryableCodes = /* @__PURE__ */ new Set([
46850
+ ...retryableGrpcStatusCodes,
46851
+ ...additionalStatusCodes
46852
+ ]);
46853
+ const idempotencyKey = uuidv4();
46854
+ const startTime = Date.now();
46855
+ let attempt = 0;
46856
+ let delayMs = baseDelay;
46857
+ logger.debug("Sending gRPC request", "method", call.method.path);
46858
+ while (true) {
46859
+ const metadata = new Metadata(restOptions.metadata ?? {});
46860
+ metadata.set("x-idempotency-key", idempotencyKey);
46861
+ metadata.set("x-retry-attempt", String(attempt));
46862
+ if (attempt > 0) {
46863
+ metadata.set(
46864
+ "x-retry-delay",
46865
+ ((Date.now() - startTime) / 1e3).toFixed(3)
46866
+ );
46867
+ }
46868
+ try {
46869
+ return yield* call.next(call.request, {
46870
+ ...restOptions,
46871
+ metadata,
46872
+ signal
46873
+ });
46874
+ } catch (err) {
46875
+ if (!(err instanceof ClientError9) || !retryableCodes.has(err.code) || attempt >= retries) {
46876
+ if (attempt === retries && attempt > 0) {
46877
+ logger.debug(
46878
+ "Final retry attempt failed",
46879
+ "error",
46880
+ err,
46881
+ "retries",
46882
+ attempt,
46883
+ "delay",
46884
+ delayMs,
46885
+ "method",
46886
+ call.method.path,
46887
+ "idempotency_key",
46888
+ idempotencyKey.substring(0, 8)
46889
+ );
46890
+ }
46891
+ throw err;
46892
+ }
46893
+ if (attempt > 0) {
46894
+ logger.debug(
46895
+ "Retryable failure",
46896
+ "error",
46897
+ err,
46898
+ "retries",
46899
+ attempt,
46900
+ "delay",
46901
+ delayMs,
46902
+ "method",
46903
+ call.method.path,
46904
+ "idempotency_key",
46905
+ idempotencyKey.substring(0, 8)
46906
+ );
46907
+ }
46908
+ await sleep(delayMs, signal);
46909
+ delayMs = Math.min(delayMs * delayFactor, maxDelay);
46910
+ attempt += 1;
46911
+ }
46912
+ }
46913
+ };
46559
46914
  }
46560
46915
  authMiddleware(profile) {
46561
46916
  const getOrCreateAuthTokenManager = () => {
46562
46917
  if (!this.authTokenManager) {
46563
- this.authTokenManager = new AuthTokenManager(this.cpClient);
46918
+ this.authTokenManager = new AuthTokenManager(
46919
+ this.cpClient,
46920
+ this.logger
46921
+ );
46564
46922
  this.authTokenManager.start();
46565
46923
  }
46566
46924
  return this.authTokenManager;
@@ -46650,53 +47008,6 @@ var sleep = (ms, signal) => new Promise((resolve, reject) => {
46650
47008
  { once: true }
46651
47009
  );
46652
47010
  });
46653
- var retryMiddleware = async function* retryMiddleware2(call, options) {
46654
- const {
46655
- retries = 3,
46656
- baseDelay = 100,
46657
- maxDelay = 1e3,
46658
- delayFactor = 2,
46659
- additionalStatusCodes = [],
46660
- signal,
46661
- ...restOptions
46662
- } = options;
46663
- if (call.requestStream || call.responseStream || !retries) {
46664
- return yield* call.next(call.request, restOptions);
46665
- }
46666
- const retryableCodes = /* @__PURE__ */ new Set([
46667
- ...retryableGrpcStatusCodes,
46668
- ...additionalStatusCodes
46669
- ]);
46670
- const idempotencyKey = uuidv4();
46671
- const startTime = Date.now();
46672
- let attempt = 0;
46673
- let delayMs = baseDelay;
46674
- while (true) {
46675
- const metadata = new Metadata(restOptions.metadata ?? {});
46676
- metadata.set("x-idempotency-key", idempotencyKey);
46677
- metadata.set("x-retry-attempt", String(attempt));
46678
- if (attempt > 0) {
46679
- metadata.set(
46680
- "x-retry-delay",
46681
- ((Date.now() - startTime) / 1e3).toFixed(3)
46682
- );
46683
- }
46684
- try {
46685
- return yield* call.next(call.request, {
46686
- ...restOptions,
46687
- metadata,
46688
- signal
46689
- });
46690
- } catch (err) {
46691
- if (!(err instanceof ClientError9) || !retryableCodes.has(err.code) || attempt >= retries) {
46692
- throw err;
46693
- }
46694
- await sleep(delayMs, signal);
46695
- delayMs = Math.min(delayMs * delayFactor, maxDelay);
46696
- attempt += 1;
46697
- }
46698
- }
46699
- };
46700
47011
  var defaultClient;
46701
47012
  var defaultClientOptions;
46702
47013
  function getDefaultClient() {
@@ -46740,6 +47051,13 @@ var AppService = class {
46740
47051
  environmentName: this.#client.environmentName(params.environment),
46741
47052
  objectCreationType: params.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
46742
47053
  });
47054
+ this.#client.logger.debug(
47055
+ "Retrieved App",
47056
+ "app_id",
47057
+ resp.appId,
47058
+ "app_name",
47059
+ name
47060
+ );
46743
47061
  return new App2(resp.appId, name);
46744
47062
  } catch (err) {
46745
47063
  if (err instanceof ClientError10 && err.code === Status10.NOT_FOUND)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modal",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Modal SDK for JavaScript/TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://modal.com/docs/guide/sdk-javascript-go",