modal 0.3.16 → 0.3.17

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
@@ -38797,70 +38797,7 @@ function initializeClient(options) {
38797
38797
  client = createClient(mergedProfile);
38798
38798
  }
38799
38799
 
38800
- // src/image.ts
38801
- var Image2 = class {
38802
- imageId;
38803
- /** @ignore */
38804
- constructor(imageId) {
38805
- this.imageId = imageId;
38806
- }
38807
- };
38808
- async function fromRegistryInternal(appId, tag, imageRegistryConfig) {
38809
- const resp = await client.imageGetOrCreate({
38810
- appId,
38811
- image: {
38812
- dockerfileCommands: [`FROM ${tag}`],
38813
- imageRegistryConfig
38814
- },
38815
- builderVersion: imageBuilderVersion()
38816
- });
38817
- let result;
38818
- let metadata = void 0;
38819
- if (resp.result?.status) {
38820
- result = resp.result;
38821
- metadata = resp.metadata;
38822
- } else {
38823
- let lastEntryId = "";
38824
- let resultJoined = void 0;
38825
- while (!resultJoined) {
38826
- for await (const item of client.imageJoinStreaming({
38827
- imageId: resp.imageId,
38828
- timeout: 55,
38829
- lastEntryId
38830
- })) {
38831
- if (item.entryId) lastEntryId = item.entryId;
38832
- if (item.result?.status) {
38833
- resultJoined = item.result;
38834
- metadata = item.metadata;
38835
- break;
38836
- }
38837
- }
38838
- }
38839
- result = resultJoined;
38840
- }
38841
- void metadata;
38842
- if (result.status === 2 /* GENERIC_STATUS_FAILURE */) {
38843
- throw new Error(
38844
- `Image build for ${resp.imageId} failed with the exception:
38845
- ${result.exception}`
38846
- );
38847
- } else if (result.status === 3 /* GENERIC_STATUS_TERMINATED */) {
38848
- throw new Error(
38849
- `Image build for ${resp.imageId} terminated due to external shut-down. Please try again.`
38850
- );
38851
- } else if (result.status === 4 /* GENERIC_STATUS_TIMEOUT */) {
38852
- throw new Error(
38853
- `Image build for ${resp.imageId} timed out. Please try again with a larger timeout parameter.`
38854
- );
38855
- } else if (result.status !== 1 /* GENERIC_STATUS_SUCCESS */) {
38856
- throw new Error(
38857
- `Image build for ${resp.imageId} failed with unknown status: ${result.status}`
38858
- );
38859
- }
38860
- return new Image2(resp.imageId);
38861
- }
38862
-
38863
- // src/sandbox.ts
38800
+ // src/secret.ts
38864
38801
  import { ClientError as ClientError2, Status as Status2 } from "nice-grpc";
38865
38802
 
38866
38803
  // src/errors.ts
@@ -38919,6 +38856,200 @@ var SandboxTimeoutError = class extends Error {
38919
38856
  }
38920
38857
  };
38921
38858
 
38859
+ // src/secret.ts
38860
+ var Secret = class _Secret {
38861
+ secretId;
38862
+ name;
38863
+ /** @ignore */
38864
+ constructor(secretId, name) {
38865
+ this.secretId = secretId;
38866
+ this.name = name;
38867
+ }
38868
+ /** Reference a Secret by its name. */
38869
+ static async fromName(name, options) {
38870
+ try {
38871
+ const resp = await client.secretGetOrCreate({
38872
+ deploymentName: name,
38873
+ environmentName: environmentName(options?.environment),
38874
+ requiredKeys: options?.requiredKeys ?? []
38875
+ });
38876
+ return new _Secret(resp.secretId, name);
38877
+ } catch (err) {
38878
+ if (err instanceof ClientError2 && err.code === Status2.NOT_FOUND)
38879
+ throw new NotFoundError(err.details);
38880
+ if (err instanceof ClientError2 && err.code === Status2.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
38881
+ throw new NotFoundError(err.details);
38882
+ throw err;
38883
+ }
38884
+ }
38885
+ /** Create a Secret from a plain object of key-value pairs. */
38886
+ static async fromObject(entries, options) {
38887
+ for (const [, value] of Object.entries(entries)) {
38888
+ if (value == null || typeof value !== "string") {
38889
+ throw new InvalidError(
38890
+ "entries must be an object mapping string keys to string values, but got:\n" + JSON.stringify(entries)
38891
+ );
38892
+ }
38893
+ }
38894
+ try {
38895
+ const resp = await client.secretGetOrCreate({
38896
+ objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
38897
+ envDict: entries,
38898
+ environmentName: environmentName(options?.environment)
38899
+ });
38900
+ return new _Secret(resp.secretId);
38901
+ } catch (err) {
38902
+ if (err instanceof ClientError2 && (err.code === Status2.INVALID_ARGUMENT || err.code === Status2.FAILED_PRECONDITION))
38903
+ throw new InvalidError(err.details);
38904
+ throw err;
38905
+ }
38906
+ }
38907
+ };
38908
+
38909
+ // src/image.ts
38910
+ var Image2 = class _Image {
38911
+ #imageId;
38912
+ #tag;
38913
+ #imageRegistryConfig;
38914
+ /** @ignore */
38915
+ constructor(imageId, tag, imageRegistryConfig) {
38916
+ this.#imageId = imageId;
38917
+ this.#tag = tag;
38918
+ this.#imageRegistryConfig = imageRegistryConfig;
38919
+ }
38920
+ get imageId() {
38921
+ return this.#imageId;
38922
+ }
38923
+ /**
38924
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
38925
+ *
38926
+ * @param tag - The registry tag for the image.
38927
+ * @param secret - Optional. A `Secret` instance containing credentials for registry authentication.
38928
+ */
38929
+ static fromRegistry(tag, secret) {
38930
+ let imageRegistryConfig;
38931
+ if (secret) {
38932
+ if (!(secret instanceof Secret)) {
38933
+ throw new TypeError(
38934
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
38935
+ );
38936
+ }
38937
+ imageRegistryConfig = {
38938
+ registryAuthType: 4 /* REGISTRY_AUTH_TYPE_STATIC_CREDS */,
38939
+ secretId: secret.secretId
38940
+ };
38941
+ }
38942
+ return new _Image("", tag, imageRegistryConfig);
38943
+ }
38944
+ /**
38945
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
38946
+ *
38947
+ * @param tag - The registry tag for the image.
38948
+ * @param secret - A `Secret` instance containing credentials for registry authentication.
38949
+ */
38950
+ static fromAwsEcr(tag, secret) {
38951
+ let imageRegistryConfig;
38952
+ if (secret) {
38953
+ if (!(secret instanceof Secret)) {
38954
+ throw new TypeError(
38955
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
38956
+ );
38957
+ }
38958
+ imageRegistryConfig = {
38959
+ registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
38960
+ secretId: secret.secretId
38961
+ };
38962
+ }
38963
+ return new _Image("", tag, imageRegistryConfig);
38964
+ }
38965
+ /**
38966
+ * Creates an `Image` instance from a raw registry tag, optionally using a secret for authentication.
38967
+ *
38968
+ * @param tag - The registry tag for the image.
38969
+ * @param secret - A `Secret` instance containing credentials for registry authentication.
38970
+ */
38971
+ static fromGcpArtifactRegistry(tag, secret) {
38972
+ let imageRegistryConfig;
38973
+ if (secret) {
38974
+ if (!(secret instanceof Secret)) {
38975
+ throw new TypeError(
38976
+ "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
38977
+ );
38978
+ }
38979
+ imageRegistryConfig = {
38980
+ registryAuthType: 2 /* REGISTRY_AUTH_TYPE_GCP */,
38981
+ secretId: secret.secretId
38982
+ };
38983
+ }
38984
+ return new _Image("", tag, imageRegistryConfig);
38985
+ }
38986
+ /**
38987
+ * @internal
38988
+ * Build image object
38989
+ */
38990
+ async _build(appId) {
38991
+ if (this.imageId !== "") {
38992
+ return this;
38993
+ }
38994
+ const resp = await client.imageGetOrCreate({
38995
+ appId,
38996
+ image: {
38997
+ dockerfileCommands: [`FROM ${this.#tag}`],
38998
+ imageRegistryConfig: this.#imageRegistryConfig
38999
+ },
39000
+ builderVersion: imageBuilderVersion()
39001
+ });
39002
+ let result;
39003
+ let metadata = void 0;
39004
+ if (resp.result?.status) {
39005
+ result = resp.result;
39006
+ metadata = resp.metadata;
39007
+ } else {
39008
+ let lastEntryId = "";
39009
+ let resultJoined = void 0;
39010
+ while (!resultJoined) {
39011
+ for await (const item of client.imageJoinStreaming({
39012
+ imageId: resp.imageId,
39013
+ timeout: 55,
39014
+ lastEntryId
39015
+ })) {
39016
+ if (item.entryId) lastEntryId = item.entryId;
39017
+ if (item.result?.status) {
39018
+ resultJoined = item.result;
39019
+ metadata = item.metadata;
39020
+ break;
39021
+ }
39022
+ }
39023
+ }
39024
+ result = resultJoined;
39025
+ }
39026
+ void metadata;
39027
+ if (result.status === 2 /* GENERIC_STATUS_FAILURE */) {
39028
+ throw new Error(
39029
+ `Image build for ${resp.imageId} failed with the exception:
39030
+ ${result.exception}`
39031
+ );
39032
+ } else if (result.status === 3 /* GENERIC_STATUS_TERMINATED */) {
39033
+ throw new Error(
39034
+ `Image build for ${resp.imageId} terminated due to external shut-down. Please try again.`
39035
+ );
39036
+ } else if (result.status === 4 /* GENERIC_STATUS_TIMEOUT */) {
39037
+ throw new Error(
39038
+ `Image build for ${resp.imageId} timed out. Please try again with a larger timeout parameter.`
39039
+ );
39040
+ } else if (result.status !== 1 /* GENERIC_STATUS_SUCCESS */) {
39041
+ throw new Error(
39042
+ `Image build for ${resp.imageId} failed with unknown status: ${result.status}`
39043
+ );
39044
+ }
39045
+ this.#imageId = resp.imageId;
39046
+ return this;
39047
+ }
39048
+ };
39049
+
39050
+ // src/sandbox.ts
39051
+ import { ClientError as ClientError3, Status as Status3 } from "nice-grpc";
39052
+
38922
39053
  // src/sandbox_filesystem.ts
38923
39054
  var SandboxFile = class {
38924
39055
  #fileDescriptor;
@@ -39182,6 +39313,25 @@ var Sandbox2 = class _Sandbox {
39182
39313
  ).pipeThrough(new TextDecoderStream())
39183
39314
  );
39184
39315
  }
39316
+ /** Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`. */
39317
+ async setTags(tags) {
39318
+ const tagsList = Object.entries(tags).map(([tagName, tagValue]) => ({
39319
+ tagName,
39320
+ tagValue
39321
+ }));
39322
+ try {
39323
+ await client.sandboxTagsSet({
39324
+ environmentName: environmentName(),
39325
+ sandboxId: this.sandboxId,
39326
+ tags: tagsList
39327
+ });
39328
+ } catch (err) {
39329
+ if (err instanceof ClientError3 && err.code === Status3.INVALID_ARGUMENT) {
39330
+ throw new InvalidError(err.details || err.message);
39331
+ }
39332
+ throw err;
39333
+ }
39334
+ }
39185
39335
  /** Returns a running Sandbox object from an ID.
39186
39336
  *
39187
39337
  * @returns Sandbox with ID
@@ -39193,7 +39343,7 @@ var Sandbox2 = class _Sandbox {
39193
39343
  timeout: 0
39194
39344
  });
39195
39345
  } catch (err) {
39196
- if (err instanceof ClientError2 && err.code === Status2.NOT_FOUND)
39346
+ if (err instanceof ClientError3 && err.code === Status3.NOT_FOUND)
39197
39347
  throw new NotFoundError(`Sandbox with id: '${sandboxId}' not found`);
39198
39348
  throw err;
39199
39349
  }
@@ -39256,7 +39406,7 @@ var Sandbox2 = class _Sandbox {
39256
39406
  while (true) {
39257
39407
  const resp = await client.sandboxWait({
39258
39408
  sandboxId: this.sandboxId,
39259
- timeout: 55
39409
+ timeout: 10
39260
39410
  });
39261
39411
  if (resp.result) {
39262
39412
  return _Sandbox.#getReturnCode(resp.result);
@@ -39313,7 +39463,7 @@ var Sandbox2 = class _Sandbox {
39313
39463
  if (!resp.imageId) {
39314
39464
  throw new Error("Sandbox snapshot response missing image ID");
39315
39465
  }
39316
- return new Image2(resp.imageId);
39466
+ return new Image2(resp.imageId, "");
39317
39467
  }
39318
39468
  /**
39319
39469
  * Check if the Sandbox has finished running.
@@ -39327,6 +39477,41 @@ var Sandbox2 = class _Sandbox {
39327
39477
  });
39328
39478
  return _Sandbox.#getReturnCode(resp.result);
39329
39479
  }
39480
+ /**
39481
+ * List all Sandboxes for the current Environment or App ID (if specified).
39482
+ * If tags are specified, only Sandboxes that have at least those tags are returned.
39483
+ */
39484
+ static async *list(options = {}) {
39485
+ const env = environmentName(options.environment);
39486
+ const tagsList = options.tags ? Object.entries(options.tags).map(([tagName, tagValue]) => ({
39487
+ tagName,
39488
+ tagValue
39489
+ })) : [];
39490
+ let beforeTimestamp = void 0;
39491
+ while (true) {
39492
+ try {
39493
+ const resp = await client.sandboxList({
39494
+ appId: options.appId,
39495
+ beforeTimestamp,
39496
+ environmentName: env,
39497
+ includeFinished: false,
39498
+ tags: tagsList
39499
+ });
39500
+ if (!resp.sandboxes || resp.sandboxes.length === 0) {
39501
+ return;
39502
+ }
39503
+ for (const info of resp.sandboxes) {
39504
+ yield new _Sandbox(info.id);
39505
+ }
39506
+ beforeTimestamp = resp.sandboxes[resp.sandboxes.length - 1].createdAt;
39507
+ } catch (err) {
39508
+ if (err instanceof ClientError3 && err.code === Status3.INVALID_ARGUMENT) {
39509
+ throw new InvalidError(err.details || err.message);
39510
+ }
39511
+ throw err;
39512
+ }
39513
+ }
39514
+ }
39330
39515
  static #getReturnCode(result) {
39331
39516
  if (result === void 0 || result.status === 0 /* GENERIC_STATUS_UNSPECIFIED */) {
39332
39517
  return null;
@@ -39492,39 +39677,99 @@ function encodeIfString(chunk) {
39492
39677
  return typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk;
39493
39678
  }
39494
39679
 
39495
- // src/secret.ts
39496
- import { ClientError as ClientError3, Status as Status3 } from "nice-grpc";
39497
- var Secret = class _Secret {
39498
- secretId;
39499
- /** @ignore */
39500
- constructor(secretId) {
39501
- this.secretId = secretId;
39502
- }
39503
- /** Reference a Secret by its name. */
39504
- static async fromName(name, options) {
39505
- try {
39506
- const resp = await client.secretGetOrCreate({
39507
- deploymentName: name,
39508
- environmentName: environmentName(options?.environment),
39509
- requiredKeys: options?.requiredKeys ?? []
39510
- });
39511
- return new _Secret(resp.secretId);
39512
- } catch (err) {
39513
- if (err instanceof ClientError3 && err.code === Status3.NOT_FOUND)
39514
- throw new NotFoundError(err.details);
39515
- if (err instanceof ClientError3 && err.code === Status3.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
39516
- throw new NotFoundError(err.details);
39517
- throw err;
39680
+ // src/cloud_bucket_mount.ts
39681
+ var CloudBucketMount2 = class {
39682
+ bucketName;
39683
+ secret;
39684
+ readOnly;
39685
+ requesterPays;
39686
+ bucketEndpointUrl;
39687
+ keyPrefix;
39688
+ oidcAuthRoleArn;
39689
+ constructor(bucketName, options = {}) {
39690
+ this.bucketName = bucketName;
39691
+ this.secret = options.secret;
39692
+ this.readOnly = options.readOnly ?? false;
39693
+ this.requesterPays = options.requesterPays ?? false;
39694
+ this.bucketEndpointUrl = options.bucketEndpointUrl;
39695
+ this.keyPrefix = options.keyPrefix;
39696
+ this.oidcAuthRoleArn = options.oidcAuthRoleArn;
39697
+ if (this.bucketEndpointUrl) {
39698
+ const url = new URL(this.bucketEndpointUrl);
39699
+ if (!url.hostname.endsWith("r2.cloudflarestorage.com") && !url.hostname.endsWith("storage.googleapis.com")) {
39700
+ console.warn(
39701
+ "CloudBucketMount received unrecognized bucket endpoint URL. Assuming AWS S3 configuration as fallback."
39702
+ );
39703
+ }
39704
+ }
39705
+ if (this.requesterPays && !this.secret) {
39706
+ throw new Error("Credentials required in order to use Requester Pays.");
39707
+ }
39708
+ if (this.keyPrefix && !this.keyPrefix.endsWith("/")) {
39709
+ throw new Error(
39710
+ "keyPrefix will be prefixed to all object paths, so it must end in a '/'"
39711
+ );
39518
39712
  }
39519
39713
  }
39520
39714
  };
39715
+ function endpointUrlToBucketType(bucketEndpointUrl) {
39716
+ if (!bucketEndpointUrl) {
39717
+ return 1 /* S3 */;
39718
+ }
39719
+ const url = new URL(bucketEndpointUrl);
39720
+ if (url.hostname.endsWith("r2.cloudflarestorage.com")) {
39721
+ return 2 /* R2 */;
39722
+ } else if (url.hostname.endsWith("storage.googleapis.com")) {
39723
+ return 3 /* GCP */;
39724
+ } else {
39725
+ return 1 /* S3 */;
39726
+ }
39727
+ }
39728
+ function cloudBucketMountToProto(mount, mountPath) {
39729
+ return {
39730
+ bucketName: mount.bucketName,
39731
+ mountPath,
39732
+ credentialsSecretId: mount.secret?.secretId ?? "",
39733
+ readOnly: mount.readOnly,
39734
+ bucketType: endpointUrlToBucketType(mount.bucketEndpointUrl),
39735
+ requesterPays: mount.requesterPays,
39736
+ bucketEndpointUrl: mount.bucketEndpointUrl,
39737
+ keyPrefix: mount.keyPrefix,
39738
+ oidcAuthRoleArn: mount.oidcAuthRoleArn
39739
+ };
39740
+ }
39521
39741
 
39522
39742
  // src/app.ts
39743
+ function parseGpuConfig(gpu) {
39744
+ if (!gpu) {
39745
+ return void 0;
39746
+ }
39747
+ let gpuType = gpu;
39748
+ let count = 1;
39749
+ if (gpu.includes(":")) {
39750
+ const [type, countStr] = gpu.split(":", 2);
39751
+ gpuType = type;
39752
+ count = parseInt(countStr, 10);
39753
+ if (isNaN(count) || count < 1) {
39754
+ throw new Error(
39755
+ `Invalid GPU count: ${countStr}. Value must be a positive integer.`
39756
+ );
39757
+ }
39758
+ }
39759
+ return {
39760
+ type: 0,
39761
+ // Deprecated field, but required by proto
39762
+ count,
39763
+ gpuType: gpuType.toUpperCase()
39764
+ };
39765
+ }
39523
39766
  var App = class _App {
39524
39767
  appId;
39768
+ name;
39525
39769
  /** @ignore */
39526
- constructor(appId) {
39770
+ constructor(appId, name) {
39527
39771
  this.appId = appId;
39772
+ this.name = name;
39528
39773
  }
39529
39774
  /** Lookup a deployed app by name, or create if it does not exist. */
39530
39775
  static async lookup(name, options = {}) {
@@ -39534,7 +39779,7 @@ var App = class _App {
39534
39779
  environmentName: environmentName(options.environment),
39535
39780
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
39536
39781
  });
39537
- return new _App(resp.appId);
39782
+ return new _App(resp.appId, name);
39538
39783
  } catch (err) {
39539
39784
  if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
39540
39785
  throw new NotFoundError(`App '${name}' not found`);
@@ -39542,17 +39787,27 @@ var App = class _App {
39542
39787
  }
39543
39788
  }
39544
39789
  async createSandbox(image, options = {}) {
39790
+ const gpuConfig = parseGpuConfig(options.gpu);
39545
39791
  if (options.timeout && options.timeout % 1e3 !== 0) {
39546
39792
  throw new Error(
39547
39793
  `Timeout must be a multiple of 1000ms, got ${options.timeout}`
39548
39794
  );
39549
39795
  }
39796
+ await image._build(this.appId);
39797
+ if (options.workdir && !options.workdir.startsWith("/")) {
39798
+ throw new Error(
39799
+ `workdir must be an absolute path, got: ${options.workdir}`
39800
+ );
39801
+ }
39550
39802
  const volumeMounts = options.volumes ? Object.entries(options.volumes).map(([mountPath, volume]) => ({
39551
39803
  volumeId: volume.volumeId,
39552
39804
  mountPath,
39553
39805
  allowBackgroundCommits: true,
39554
- readOnly: false
39806
+ readOnly: volume.isReadOnly
39555
39807
  })) : [];
39808
+ const cloudBucketMounts = options.cloudBucketMounts ? Object.entries(options.cloudBucketMounts).map(
39809
+ ([mountPath, mount]) => cloudBucketMountToProto(mount, mountPath)
39810
+ ) : [];
39556
39811
  const openPorts = [];
39557
39812
  if (options.encryptedPorts) {
39558
39813
  openPorts.push(
@@ -39580,6 +39835,31 @@ var App = class _App {
39580
39835
  );
39581
39836
  }
39582
39837
  const secretIds = options.secrets ? options.secrets.map((secret) => secret.secretId) : [];
39838
+ let networkAccess;
39839
+ if (options.blockNetwork) {
39840
+ if (options.cidrAllowlist) {
39841
+ throw new Error(
39842
+ "cidrAllowlist cannot be used when blockNetwork is enabled"
39843
+ );
39844
+ }
39845
+ networkAccess = {
39846
+ networkAccessType: 2 /* BLOCKED */,
39847
+ allowedCidrs: []
39848
+ };
39849
+ } else if (options.cidrAllowlist) {
39850
+ networkAccess = {
39851
+ networkAccessType: 3 /* ALLOWLIST */,
39852
+ allowedCidrs: options.cidrAllowlist
39853
+ };
39854
+ } else {
39855
+ networkAccess = {
39856
+ networkAccessType: 1 /* OPEN */,
39857
+ allowedCidrs: []
39858
+ };
39859
+ }
39860
+ const schedulerPlacement = SchedulerPlacement.create({
39861
+ regions: options.regions ?? []
39862
+ });
39583
39863
  const createResp = await client.sandboxCreate({
39584
39864
  appId: this.appId,
39585
39865
  definition: {
@@ -39587,59 +39867,43 @@ var App = class _App {
39587
39867
  entrypointArgs: options.command ?? ["sleep", "48h"],
39588
39868
  imageId: image.imageId,
39589
39869
  timeoutSecs: options.timeout != void 0 ? options.timeout / 1e3 : 600,
39590
- networkAccess: {
39591
- networkAccessType: 1 /* OPEN */
39592
- },
39870
+ workdir: options.workdir ?? void 0,
39871
+ networkAccess,
39593
39872
  resources: {
39594
39873
  // https://modal.com/docs/guide/resources
39595
39874
  milliCpu: Math.round(1e3 * (options.cpu ?? 0.125)),
39596
- memoryMb: options.memory ?? 128
39875
+ memoryMb: options.memory ?? 128,
39876
+ gpuConfig
39597
39877
  },
39598
39878
  volumeMounts,
39879
+ cloudBucketMounts,
39599
39880
  secretIds,
39600
- openPorts: openPorts.length > 0 ? { ports: openPorts } : void 0
39881
+ openPorts: openPorts.length > 0 ? { ports: openPorts } : void 0,
39882
+ cloudProviderStr: options.cloud ?? "",
39883
+ schedulerPlacement,
39884
+ verbose: options.verbose ?? false,
39885
+ proxyId: options.proxy?.proxyId
39601
39886
  }
39602
39887
  });
39603
39888
  return new Sandbox2(createResp.sandboxId);
39604
39889
  }
39890
+ /**
39891
+ * @deprecated Use `Image.fromRegistry` instead.
39892
+ */
39605
39893
  async imageFromRegistry(tag, secret) {
39606
- let imageRegistryConfig;
39607
- if (secret) {
39608
- if (!(secret instanceof Secret)) {
39609
- throw new TypeError(
39610
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39611
- );
39612
- }
39613
- imageRegistryConfig = {
39614
- registryAuthType: 4 /* REGISTRY_AUTH_TYPE_STATIC_CREDS */,
39615
- secretId: secret.secretId
39616
- };
39617
- }
39618
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39894
+ return await Image2.fromRegistry(tag, secret)._build(this.appId);
39619
39895
  }
39896
+ /**
39897
+ * @deprecated Use `Image.fromAwsEcr` instead.
39898
+ */
39620
39899
  async imageFromAwsEcr(tag, secret) {
39621
- if (!(secret instanceof Secret)) {
39622
- throw new TypeError(
39623
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39624
- );
39625
- }
39626
- const imageRegistryConfig = {
39627
- registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
39628
- secretId: secret.secretId
39629
- };
39630
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39900
+ return await Image2.fromAwsEcr(tag, secret)._build(this.appId);
39631
39901
  }
39902
+ /**
39903
+ * @deprecated Use `Image.fromGcpArtifactRegistry` instead.
39904
+ */
39632
39905
  async imageFromGcpArtifactRegistry(tag, secret) {
39633
- if (!(secret instanceof Secret)) {
39634
- throw new TypeError(
39635
- "secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
39636
- );
39637
- }
39638
- const imageRegistryConfig = {
39639
- registryAuthType: 2 /* REGISTRY_AUTH_TYPE_GCP */,
39640
- secretId: secret.secretId
39641
- };
39642
- return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
39906
+ return await Image2.fromGcpArtifactRegistry(tag, secret)._build(this.appId);
39643
39907
  }
39644
39908
  };
39645
39909
 
@@ -40224,11 +40488,13 @@ var Function_ = class _Function_ {
40224
40488
  functionId;
40225
40489
  methodName;
40226
40490
  #inputPlaneUrl;
40491
+ #webUrl;
40227
40492
  /** @ignore */
40228
- constructor(functionId, methodName, inputPlaneUrl) {
40493
+ constructor(functionId, methodName, inputPlaneUrl, webUrl) {
40229
40494
  this.functionId = functionId;
40230
40495
  this.methodName = methodName;
40231
40496
  this.#inputPlaneUrl = inputPlaneUrl;
40497
+ this.#webUrl = webUrl;
40232
40498
  }
40233
40499
  static async lookup(appName, name, options = {}) {
40234
40500
  try {
@@ -40240,7 +40506,8 @@ var Function_ = class _Function_ {
40240
40506
  return new _Function_(
40241
40507
  resp.functionId,
40242
40508
  void 0,
40243
- resp.handleMetadata?.inputPlaneUrl
40509
+ resp.handleMetadata?.inputPlaneUrl,
40510
+ resp.handleMetadata?.webUrl
40244
40511
  );
40245
40512
  } catch (err) {
40246
40513
  if (err instanceof ClientError5 && err.code === Status5.NOT_FOUND)
@@ -40290,6 +40557,38 @@ var Function_ = class _Function_ {
40290
40557
  );
40291
40558
  return new FunctionCall(invocation.functionCallId);
40292
40559
  }
40560
+ // Returns statistics about the Function.
40561
+ async getCurrentStats() {
40562
+ const resp = await client.functionGetCurrentStats(
40563
+ { functionId: this.functionId },
40564
+ { timeout: 1e4 }
40565
+ );
40566
+ return {
40567
+ backlog: resp.backlog,
40568
+ numTotalRunners: resp.numTotalTasks
40569
+ };
40570
+ }
40571
+ // Overrides the current autoscaler behavior for this Function.
40572
+ async updateAutoscaler(options) {
40573
+ await client.functionUpdateSchedulingParams({
40574
+ functionId: this.functionId,
40575
+ warmPoolSizeOverride: 0,
40576
+ // Deprecated field, always set to 0
40577
+ settings: {
40578
+ minContainers: options.minContainers,
40579
+ maxContainers: options.maxContainers,
40580
+ bufferContainers: options.bufferContainers,
40581
+ scaledownWindow: options.scaledownWindow
40582
+ }
40583
+ });
40584
+ }
40585
+ /**
40586
+ * URL of a Function running as a web endpoint.
40587
+ * @returns The web URL if this function is a web endpoint, otherwise undefined
40588
+ */
40589
+ async getWebUrl() {
40590
+ return this.#webUrl || void 0;
40591
+ }
40293
40592
  async #createInput(args = [], kwargs = {}) {
40294
40593
  const payload = dumps([args, kwargs]);
40295
40594
  let argsBlobId = void 0;
@@ -40486,11 +40785,13 @@ var queueInitialPutBackoff = 100;
40486
40785
  var queueDefaultPartitionTtl = 24 * 3600 * 1e3;
40487
40786
  var Queue = class _Queue {
40488
40787
  queueId;
40788
+ name;
40489
40789
  #ephemeral;
40490
40790
  #abortController;
40491
40791
  /** @ignore */
40492
- constructor(queueId, ephemeral = false) {
40792
+ constructor(queueId, name, ephemeral = false) {
40493
40793
  this.queueId = queueId;
40794
+ this.name = name;
40494
40795
  this.#ephemeral = ephemeral;
40495
40796
  this.#abortController = ephemeral ? new AbortController() : void 0;
40496
40797
  }
@@ -40515,7 +40816,7 @@ var Queue = class _Queue {
40515
40816
  objectCreationType: 5 /* OBJECT_CREATION_TYPE_EPHEMERAL */,
40516
40817
  environmentName: environmentName(options.environment)
40517
40818
  });
40518
- const queue = new _Queue(resp.queueId, true);
40819
+ const queue = new _Queue(resp.queueId, void 0, true);
40519
40820
  const signal = queue.#abortController.signal;
40520
40821
  (async () => {
40521
40822
  while (true) {
@@ -40549,7 +40850,7 @@ var Queue = class _Queue {
40549
40850
  objectCreationType: options.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : void 0,
40550
40851
  environmentName: environmentName(options.environment)
40551
40852
  });
40552
- return new _Queue(resp.queueId);
40853
+ return new _Queue(resp.queueId, name);
40553
40854
  }
40554
40855
  /** Delete a queue by name. */
40555
40856
  static async delete(name, options = {}) {
@@ -40729,9 +41030,13 @@ var Queue = class _Queue {
40729
41030
  import { ClientError as ClientError8, Status as Status8 } from "nice-grpc";
40730
41031
  var Volume = class _Volume {
40731
41032
  volumeId;
41033
+ name;
41034
+ _readOnly = false;
40732
41035
  /** @ignore */
40733
- constructor(volumeId) {
41036
+ constructor(volumeId, name, readOnly = false) {
40734
41037
  this.volumeId = volumeId;
41038
+ this.name = name;
41039
+ this._readOnly = readOnly;
40735
41040
  }
40736
41041
  static async fromName(name, options) {
40737
41042
  try {
@@ -40740,16 +41045,51 @@ var Volume = class _Volume {
40740
41045
  environmentName: environmentName(options?.environment),
40741
41046
  objectCreationType: options?.createIfMissing ? 1 /* OBJECT_CREATION_TYPE_CREATE_IF_MISSING */ : 0 /* OBJECT_CREATION_TYPE_UNSPECIFIED */
40742
41047
  });
40743
- return new _Volume(resp.volumeId);
41048
+ return new _Volume(resp.volumeId, name);
40744
41049
  } catch (err) {
40745
41050
  if (err instanceof ClientError8 && err.code === Status8.NOT_FOUND)
40746
41051
  throw new NotFoundError(err.details);
40747
41052
  throw err;
40748
41053
  }
40749
41054
  }
41055
+ /** Configure Volume to mount as read-only. */
41056
+ readOnly() {
41057
+ return new _Volume(this.volumeId, this.name, true);
41058
+ }
41059
+ get isReadOnly() {
41060
+ return this._readOnly;
41061
+ }
41062
+ };
41063
+
41064
+ // src/proxy.ts
41065
+ import { ClientError as ClientError9, Status as Status9 } from "nice-grpc";
41066
+ var Proxy2 = class _Proxy {
41067
+ proxyId;
41068
+ /** @ignore */
41069
+ constructor(proxyId) {
41070
+ this.proxyId = proxyId;
41071
+ }
41072
+ /** Reference a Proxy by its name. */
41073
+ static async fromName(name, options) {
41074
+ try {
41075
+ const resp = await client.proxyGet({
41076
+ name,
41077
+ environmentName: environmentName(options?.environment)
41078
+ });
41079
+ if (!resp.proxy?.proxyId) {
41080
+ throw new NotFoundError(`Proxy '${name}' not found`);
41081
+ }
41082
+ return new _Proxy(resp.proxy.proxyId);
41083
+ } catch (err) {
41084
+ if (err instanceof ClientError9 && err.code === Status9.NOT_FOUND)
41085
+ throw new NotFoundError(`Proxy '${name}' not found`);
41086
+ throw err;
41087
+ }
41088
+ }
40750
41089
  };
40751
41090
  export {
40752
41091
  App,
41092
+ CloudBucketMount2 as CloudBucketMount,
40753
41093
  Cls,
40754
41094
  ClsInstance,
40755
41095
  ContainerProcess,
@@ -40760,6 +41100,7 @@ export {
40760
41100
  InternalFailure,
40761
41101
  InvalidError,
40762
41102
  NotFoundError,
41103
+ Proxy2 as Proxy,
40763
41104
  Queue,
40764
41105
  QueueEmptyError,
40765
41106
  QueueFullError,