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.cjs +481 -138
- package/dist/index.d.cts +168 -21
- package/dist/index.d.ts +168 -21
- package/dist/index.js +479 -138
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -38797,70 +38797,7 @@ function initializeClient(options) {
|
|
|
38797
38797
|
client = createClient(mergedProfile);
|
|
38798
38798
|
}
|
|
38799
38799
|
|
|
38800
|
-
// src/
|
|
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
|
|
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:
|
|
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/
|
|
39496
|
-
|
|
39497
|
-
|
|
39498
|
-
|
|
39499
|
-
|
|
39500
|
-
|
|
39501
|
-
|
|
39502
|
-
|
|
39503
|
-
|
|
39504
|
-
|
|
39505
|
-
|
|
39506
|
-
|
|
39507
|
-
|
|
39508
|
-
|
|
39509
|
-
|
|
39510
|
-
|
|
39511
|
-
|
|
39512
|
-
|
|
39513
|
-
|
|
39514
|
-
|
|
39515
|
-
|
|
39516
|
-
|
|
39517
|
-
|
|
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:
|
|
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
|
-
|
|
39591
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|