modal 0.3.6 → 0.3.8
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/README.md +1 -1
- package/dist/index.cjs +39574 -0
- package/dist/index.d.cts +380 -0
- package/dist/index.d.ts +66 -51
- package/dist/index.js +285 -132
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/app.ts
|
|
2
|
-
import { ClientError as
|
|
2
|
+
import { ClientError as ClientError3, Status as Status3 } from "nice-grpc";
|
|
3
3
|
|
|
4
4
|
// node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
|
|
5
5
|
function varint64read() {
|
|
@@ -37797,13 +37797,13 @@ import {
|
|
|
37797
37797
|
} from "nice-grpc";
|
|
37798
37798
|
|
|
37799
37799
|
// src/config.ts
|
|
37800
|
-
import {
|
|
37801
|
-
import path from "node:path";
|
|
37800
|
+
import { readFileSync } from "node:fs";
|
|
37802
37801
|
import { homedir } from "node:os";
|
|
37802
|
+
import path from "node:path";
|
|
37803
37803
|
import { parse as parseToml } from "smol-toml";
|
|
37804
|
-
|
|
37804
|
+
function readConfigFile() {
|
|
37805
37805
|
try {
|
|
37806
|
-
const configContent =
|
|
37806
|
+
const configContent = readFileSync(path.join(homedir(), ".modal.toml"), {
|
|
37807
37807
|
encoding: "utf-8"
|
|
37808
37808
|
});
|
|
37809
37809
|
return parseToml(configContent);
|
|
@@ -37814,7 +37814,7 @@ async function readConfigFile() {
|
|
|
37814
37814
|
throw new Error(`Failed to read or parse .modal.toml: ${err.message}`);
|
|
37815
37815
|
}
|
|
37816
37816
|
}
|
|
37817
|
-
var config =
|
|
37817
|
+
var config = readConfigFile();
|
|
37818
37818
|
function getProfile(profileName) {
|
|
37819
37819
|
profileName = profileName || process.env["MODAL_PROFILE"] || void 0;
|
|
37820
37820
|
if (!profileName) {
|
|
@@ -37835,7 +37835,8 @@ function getProfile(profileName) {
|
|
|
37835
37835
|
serverUrl: process.env["MODAL_SERVER_URL"] || profileData.server_url || "https://api.modal.com:443",
|
|
37836
37836
|
tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
|
|
37837
37837
|
tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
|
|
37838
|
-
environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment
|
|
37838
|
+
environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
|
|
37839
|
+
imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion
|
|
37839
37840
|
};
|
|
37840
37841
|
if (!profile2.tokenId || !profile2.tokenSecret) {
|
|
37841
37842
|
throw new Error(
|
|
@@ -37848,6 +37849,9 @@ var profile = getProfile(process.env["MODAL_PROFILE"] || void 0);
|
|
|
37848
37849
|
function environmentName(environment) {
|
|
37849
37850
|
return environment || profile.environment || "";
|
|
37850
37851
|
}
|
|
37852
|
+
function imageBuilderVersion(version) {
|
|
37853
|
+
return version || profile.imageBuilderVersion || "2024.10";
|
|
37854
|
+
}
|
|
37851
37855
|
|
|
37852
37856
|
// src/client.ts
|
|
37853
37857
|
function authMiddleware(profile2) {
|
|
@@ -37980,15 +37984,15 @@ var Image2 = class {
|
|
|
37980
37984
|
this.imageId = imageId;
|
|
37981
37985
|
}
|
|
37982
37986
|
};
|
|
37983
|
-
async function fromRegistryInternal(appId, tag) {
|
|
37987
|
+
async function fromRegistryInternal(appId, tag, imageRegistryConfig) {
|
|
37984
37988
|
const resp = await client.imageGetOrCreate({
|
|
37985
37989
|
appId,
|
|
37986
37990
|
image: {
|
|
37987
|
-
dockerfileCommands: [`FROM ${tag}`]
|
|
37991
|
+
dockerfileCommands: [`FROM ${tag}`],
|
|
37992
|
+
imageRegistryConfig
|
|
37988
37993
|
},
|
|
37989
37994
|
namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
|
|
37990
|
-
builderVersion:
|
|
37991
|
-
// TODO: make this configurable
|
|
37995
|
+
builderVersion: imageBuilderVersion()
|
|
37992
37996
|
});
|
|
37993
37997
|
let result;
|
|
37994
37998
|
let metadata = void 0;
|
|
@@ -38403,6 +38407,34 @@ var QueueFullError = class extends Error {
|
|
|
38403
38407
|
}
|
|
38404
38408
|
};
|
|
38405
38409
|
|
|
38410
|
+
// src/secret.ts
|
|
38411
|
+
import { ClientError as ClientError2, Status as Status2 } from "nice-grpc";
|
|
38412
|
+
var Secret = class _Secret {
|
|
38413
|
+
secretId;
|
|
38414
|
+
/** @ignore */
|
|
38415
|
+
constructor(secretId) {
|
|
38416
|
+
this.secretId = secretId;
|
|
38417
|
+
}
|
|
38418
|
+
/** Reference a Secret by its name. */
|
|
38419
|
+
static async fromName(name, options) {
|
|
38420
|
+
try {
|
|
38421
|
+
const resp = await client.secretGetOrCreate({
|
|
38422
|
+
deploymentName: name,
|
|
38423
|
+
namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
|
|
38424
|
+
environmentName: environmentName(options?.environment),
|
|
38425
|
+
requiredKeys: options?.requiredKeys ?? []
|
|
38426
|
+
});
|
|
38427
|
+
return new _Secret(resp.secretId);
|
|
38428
|
+
} catch (err) {
|
|
38429
|
+
if (err instanceof ClientError2 && err.code === Status2.NOT_FOUND)
|
|
38430
|
+
throw new NotFoundError(err.details);
|
|
38431
|
+
if (err instanceof ClientError2 && err.code === Status2.FAILED_PRECONDITION && err.details.includes("Secret is missing key"))
|
|
38432
|
+
throw new NotFoundError(err.details);
|
|
38433
|
+
throw err;
|
|
38434
|
+
}
|
|
38435
|
+
}
|
|
38436
|
+
};
|
|
38437
|
+
|
|
38406
38438
|
// src/app.ts
|
|
38407
38439
|
var App = class _App {
|
|
38408
38440
|
appId;
|
|
@@ -38420,7 +38452,7 @@ var App = class _App {
|
|
|
38420
38452
|
});
|
|
38421
38453
|
return new _App(resp.appId);
|
|
38422
38454
|
} catch (err) {
|
|
38423
|
-
if (err instanceof
|
|
38455
|
+
if (err instanceof ClientError3 && err.code === Status3.NOT_FOUND)
|
|
38424
38456
|
throw new NotFoundError(`App '${name}' not found`);
|
|
38425
38457
|
throw err;
|
|
38426
38458
|
}
|
|
@@ -38453,39 +38485,26 @@ var App = class _App {
|
|
|
38453
38485
|
async imageFromRegistry(tag) {
|
|
38454
38486
|
return await fromRegistryInternal(this.appId, tag);
|
|
38455
38487
|
}
|
|
38488
|
+
async imageFromAwsEcr(tag, secret) {
|
|
38489
|
+
if (!(secret instanceof Secret)) {
|
|
38490
|
+
throw new TypeError(
|
|
38491
|
+
"secret must be a reference to an existing Secret, e.g. `await Secret.fromName('my_secret')`"
|
|
38492
|
+
);
|
|
38493
|
+
}
|
|
38494
|
+
const imageRegistryConfig = {
|
|
38495
|
+
registryAuthType: 1 /* REGISTRY_AUTH_TYPE_AWS */,
|
|
38496
|
+
secretId: secret.secretId
|
|
38497
|
+
};
|
|
38498
|
+
return await fromRegistryInternal(this.appId, tag, imageRegistryConfig);
|
|
38499
|
+
}
|
|
38456
38500
|
};
|
|
38457
38501
|
|
|
38458
38502
|
// src/cls.ts
|
|
38459
|
-
import { ClientError as
|
|
38503
|
+
import { ClientError as ClientError5, Status as Status5 } from "nice-grpc";
|
|
38460
38504
|
|
|
38461
38505
|
// src/function.ts
|
|
38462
38506
|
import { createHash } from "node:crypto";
|
|
38463
38507
|
|
|
38464
|
-
// src/function_call.ts
|
|
38465
|
-
var FunctionCall = class _FunctionCall {
|
|
38466
|
-
functionCallId;
|
|
38467
|
-
/** @ignore */
|
|
38468
|
-
constructor(functionCallId) {
|
|
38469
|
-
this.functionCallId = functionCallId;
|
|
38470
|
-
}
|
|
38471
|
-
/** Create a new function call from ID. */
|
|
38472
|
-
fromId(functionCallId) {
|
|
38473
|
-
return new _FunctionCall(functionCallId);
|
|
38474
|
-
}
|
|
38475
|
-
/** Get the result of a function call, optionally waiting with a timeout. */
|
|
38476
|
-
async get(options = {}) {
|
|
38477
|
-
const timeout = options.timeout;
|
|
38478
|
-
return await pollFunctionOutput(this.functionCallId, timeout);
|
|
38479
|
-
}
|
|
38480
|
-
/** Cancel a running function call. */
|
|
38481
|
-
async cancel(options = {}) {
|
|
38482
|
-
await client.functionCallCancel({
|
|
38483
|
-
functionCallId: this.functionCallId,
|
|
38484
|
-
terminateContainers: options.terminateContainers
|
|
38485
|
-
});
|
|
38486
|
-
}
|
|
38487
|
-
};
|
|
38488
|
-
|
|
38489
38508
|
// src/pickle.ts
|
|
38490
38509
|
var PickleError = class extends Error {
|
|
38491
38510
|
constructor(message) {
|
|
@@ -38548,6 +38567,15 @@ var Reader = class {
|
|
|
38548
38567
|
const hi = this.uint32LE() >>> 0;
|
|
38549
38568
|
return hi * 2 ** 32 + lo;
|
|
38550
38569
|
}
|
|
38570
|
+
int32LE() {
|
|
38571
|
+
const v = new DataView(
|
|
38572
|
+
this.buf.buffer,
|
|
38573
|
+
this.buf.byteOffset + this.pos,
|
|
38574
|
+
4
|
|
38575
|
+
).getInt32(0, true);
|
|
38576
|
+
this.pos += 4;
|
|
38577
|
+
return v;
|
|
38578
|
+
}
|
|
38551
38579
|
float64BE() {
|
|
38552
38580
|
const v = new DataView(
|
|
38553
38581
|
this.buf.buffer,
|
|
@@ -38680,6 +38708,7 @@ function loads(buf) {
|
|
|
38680
38708
|
const size = r.uint64LE();
|
|
38681
38709
|
void size;
|
|
38682
38710
|
}
|
|
38711
|
+
const MARK = Symbol("pickle-mark");
|
|
38683
38712
|
while (!r.eof()) {
|
|
38684
38713
|
const op = r.byte();
|
|
38685
38714
|
switch (op) {
|
|
@@ -38704,8 +38733,7 @@ function loads(buf) {
|
|
|
38704
38733
|
break;
|
|
38705
38734
|
}
|
|
38706
38735
|
case 74 /* BININT4 */: {
|
|
38707
|
-
|
|
38708
|
-
push(n >>> 31 ? n - 4294967296 : n);
|
|
38736
|
+
push(r.int32LE());
|
|
38709
38737
|
break;
|
|
38710
38738
|
}
|
|
38711
38739
|
case 71 /* BINFLOAT */:
|
|
@@ -38780,6 +38808,43 @@ function loads(buf) {
|
|
|
38780
38808
|
const _size = r.uint64LE();
|
|
38781
38809
|
break;
|
|
38782
38810
|
}
|
|
38811
|
+
case 40 /* MARK */:
|
|
38812
|
+
push(MARK);
|
|
38813
|
+
break;
|
|
38814
|
+
case 101 /* APPENDS */: {
|
|
38815
|
+
const markIndex = stack.lastIndexOf(MARK);
|
|
38816
|
+
if (markIndex === -1) {
|
|
38817
|
+
throw new PickleError("APPENDS without MARK");
|
|
38818
|
+
}
|
|
38819
|
+
const lst = stack[markIndex - 1];
|
|
38820
|
+
if (!Array.isArray(lst)) {
|
|
38821
|
+
throw new PickleError("APPENDS expects a list below MARK");
|
|
38822
|
+
}
|
|
38823
|
+
const items = stack.slice(markIndex + 1);
|
|
38824
|
+
lst.push(...items);
|
|
38825
|
+
stack.length = markIndex - 1;
|
|
38826
|
+
push(lst);
|
|
38827
|
+
break;
|
|
38828
|
+
}
|
|
38829
|
+
case 117 /* SETITEMS */: {
|
|
38830
|
+
const markIndex = stack.lastIndexOf(MARK);
|
|
38831
|
+
if (markIndex === -1) {
|
|
38832
|
+
throw new PickleError("SETITEMS without MARK");
|
|
38833
|
+
}
|
|
38834
|
+
const d = stack[markIndex - 1];
|
|
38835
|
+
if (typeof d !== "object" || d === null || Array.isArray(d)) {
|
|
38836
|
+
throw new PickleError("SETITEMS expects a dict below MARK");
|
|
38837
|
+
}
|
|
38838
|
+
const items = stack.slice(markIndex + 1);
|
|
38839
|
+
for (let i = 0; i < items.length; i += 2) {
|
|
38840
|
+
if (i + 1 < items.length) {
|
|
38841
|
+
d[items[i]] = items[i + 1];
|
|
38842
|
+
}
|
|
38843
|
+
}
|
|
38844
|
+
stack.length = markIndex - 1;
|
|
38845
|
+
push(d);
|
|
38846
|
+
break;
|
|
38847
|
+
}
|
|
38783
38848
|
default:
|
|
38784
38849
|
throw new PickleError(`Unsupported opcode 0x${op.toString(16)}`);
|
|
38785
38850
|
}
|
|
@@ -38787,79 +38852,62 @@ function loads(buf) {
|
|
|
38787
38852
|
throw new PickleError("pickle stream ended without STOP");
|
|
38788
38853
|
}
|
|
38789
38854
|
|
|
38790
|
-
// src/
|
|
38791
|
-
import { ClientError as ClientError3, Status as Status3 } from "nice-grpc";
|
|
38792
|
-
var maxObjectSizeBytes = 2 * 1024 * 1024;
|
|
38855
|
+
// src/invocation.ts
|
|
38793
38856
|
var outputsTimeout = 55 * 1e3;
|
|
38794
|
-
|
|
38795
|
-
|
|
38796
|
-
|
|
38797
|
-
|
|
38798
|
-
|
|
38799
|
-
|
|
38800
|
-
|
|
38801
|
-
|
|
38802
|
-
this.
|
|
38803
|
-
this.
|
|
38804
|
-
}
|
|
38805
|
-
static async lookup(appName, name, options = {}) {
|
|
38806
|
-
try {
|
|
38807
|
-
const resp = await client.functionGet({
|
|
38808
|
-
appName,
|
|
38809
|
-
objectTag: name,
|
|
38810
|
-
namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
|
|
38811
|
-
environmentName: environmentName(options.environment)
|
|
38812
|
-
});
|
|
38813
|
-
return new _Function_(resp.functionId);
|
|
38814
|
-
} catch (err) {
|
|
38815
|
-
if (err instanceof ClientError3 && err.code === Status3.NOT_FOUND)
|
|
38816
|
-
throw new NotFoundError(`Function '${appName}/${name}' not found`);
|
|
38817
|
-
throw err;
|
|
38818
|
-
}
|
|
38857
|
+
var ControlPlaneInvocation = class _ControlPlaneInvocation {
|
|
38858
|
+
functionCallId;
|
|
38859
|
+
input;
|
|
38860
|
+
functionCallJwt;
|
|
38861
|
+
inputJwt;
|
|
38862
|
+
constructor(functionCallId, input, functionCallJwt, inputJwt) {
|
|
38863
|
+
this.functionCallId = functionCallId;
|
|
38864
|
+
this.input = input;
|
|
38865
|
+
this.functionCallJwt = functionCallJwt;
|
|
38866
|
+
this.inputJwt = inputJwt;
|
|
38819
38867
|
}
|
|
38820
|
-
|
|
38821
|
-
|
|
38822
|
-
|
|
38823
|
-
|
|
38824
|
-
|
|
38825
|
-
|
|
38868
|
+
static async create(functionId, input, invocationType) {
|
|
38869
|
+
const functionPutInputsItem = {
|
|
38870
|
+
idx: 0,
|
|
38871
|
+
input
|
|
38872
|
+
};
|
|
38873
|
+
const functionMapResponse = await client.functionMap({
|
|
38874
|
+
functionId,
|
|
38875
|
+
functionCallType: 1 /* FUNCTION_CALL_TYPE_UNARY */,
|
|
38876
|
+
functionCallInvocationType: invocationType,
|
|
38877
|
+
pipelinedInputs: [functionPutInputsItem]
|
|
38878
|
+
});
|
|
38879
|
+
return new _ControlPlaneInvocation(
|
|
38880
|
+
functionMapResponse.functionCallId,
|
|
38881
|
+
input,
|
|
38882
|
+
functionMapResponse.functionCallJwt,
|
|
38883
|
+
functionMapResponse.pipelinedInputs[0].inputJwt
|
|
38826
38884
|
);
|
|
38827
|
-
return await pollFunctionOutput(functionCallId);
|
|
38828
38885
|
}
|
|
38829
|
-
|
|
38830
|
-
|
|
38831
|
-
const functionCallId = await this.#execFunctionCall(
|
|
38832
|
-
args,
|
|
38833
|
-
kwargs,
|
|
38834
|
-
4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */
|
|
38835
|
-
);
|
|
38836
|
-
return new FunctionCall(functionCallId);
|
|
38886
|
+
static fromFunctionCallId(functionCallId) {
|
|
38887
|
+
return new _ControlPlaneInvocation(functionCallId);
|
|
38837
38888
|
}
|
|
38838
|
-
async
|
|
38839
|
-
|
|
38840
|
-
|
|
38841
|
-
|
|
38842
|
-
|
|
38889
|
+
async awaitOutput(timeout) {
|
|
38890
|
+
return await pollFunctionOutput(this.functionCallId, timeout);
|
|
38891
|
+
}
|
|
38892
|
+
async retry(retryCount) {
|
|
38893
|
+
if (!this.input) {
|
|
38894
|
+
throw new Error("Cannot retry function invocation - input missing");
|
|
38843
38895
|
}
|
|
38844
|
-
const
|
|
38845
|
-
|
|
38846
|
-
|
|
38847
|
-
|
|
38848
|
-
|
|
38849
|
-
|
|
38850
|
-
|
|
38851
|
-
|
|
38852
|
-
args: argsBlobId ? void 0 : payload,
|
|
38853
|
-
argsBlobId,
|
|
38854
|
-
dataFormat: 1 /* DATA_FORMAT_PICKLE */,
|
|
38855
|
-
methodName: this.methodName
|
|
38856
|
-
}
|
|
38857
|
-
}
|
|
38858
|
-
]
|
|
38896
|
+
const retryItem = {
|
|
38897
|
+
inputJwt: this.inputJwt,
|
|
38898
|
+
input: this.input,
|
|
38899
|
+
retryCount
|
|
38900
|
+
};
|
|
38901
|
+
const functionRetryResponse = await client.functionRetryInputs({
|
|
38902
|
+
functionCallJwt: this.functionCallJwt,
|
|
38903
|
+
inputs: [retryItem]
|
|
38859
38904
|
});
|
|
38860
|
-
|
|
38905
|
+
this.inputJwt = functionRetryResponse.inputJwts[0];
|
|
38861
38906
|
}
|
|
38862
38907
|
};
|
|
38908
|
+
function timeNowSeconds() {
|
|
38909
|
+
return Date.now() / 1e3;
|
|
38910
|
+
}
|
|
38863
38911
|
async function pollFunctionOutput(functionCallId, timeout) {
|
|
38864
38912
|
const startTime = Date.now();
|
|
38865
38913
|
let pollTimeout = outputsTimeout;
|
|
@@ -38917,6 +38965,134 @@ async function processResult(result, dataFormat) {
|
|
|
38917
38965
|
}
|
|
38918
38966
|
return deserializeDataFormat(data, dataFormat);
|
|
38919
38967
|
}
|
|
38968
|
+
async function blobDownload(blobId) {
|
|
38969
|
+
const resp = await client.blobGet({ blobId });
|
|
38970
|
+
const s3resp = await fetch(resp.downloadUrl);
|
|
38971
|
+
if (!s3resp.ok) {
|
|
38972
|
+
throw new Error(`Failed to download blob: ${s3resp.statusText}`);
|
|
38973
|
+
}
|
|
38974
|
+
const buf = await s3resp.arrayBuffer();
|
|
38975
|
+
return new Uint8Array(buf);
|
|
38976
|
+
}
|
|
38977
|
+
function deserializeDataFormat(data, dataFormat) {
|
|
38978
|
+
if (!data) {
|
|
38979
|
+
return null;
|
|
38980
|
+
}
|
|
38981
|
+
switch (dataFormat) {
|
|
38982
|
+
case 1 /* DATA_FORMAT_PICKLE */:
|
|
38983
|
+
return loads(data);
|
|
38984
|
+
case 2 /* DATA_FORMAT_ASGI */:
|
|
38985
|
+
throw new Error("ASGI data format is not supported in Go");
|
|
38986
|
+
case 3 /* DATA_FORMAT_GENERATOR_DONE */:
|
|
38987
|
+
return GeneratorDone.decode(data);
|
|
38988
|
+
default:
|
|
38989
|
+
throw new Error(`Unsupported data format: ${dataFormat}`);
|
|
38990
|
+
}
|
|
38991
|
+
}
|
|
38992
|
+
|
|
38993
|
+
// src/function_call.ts
|
|
38994
|
+
var FunctionCall = class _FunctionCall {
|
|
38995
|
+
functionCallId;
|
|
38996
|
+
/** @ignore */
|
|
38997
|
+
constructor(functionCallId) {
|
|
38998
|
+
this.functionCallId = functionCallId;
|
|
38999
|
+
}
|
|
39000
|
+
/** Create a new function call from ID. */
|
|
39001
|
+
fromId(functionCallId) {
|
|
39002
|
+
return new _FunctionCall(functionCallId);
|
|
39003
|
+
}
|
|
39004
|
+
/** Get the result of a function call, optionally waiting with a timeout. */
|
|
39005
|
+
async get(options = {}) {
|
|
39006
|
+
const timeout = options.timeout;
|
|
39007
|
+
const invocation = ControlPlaneInvocation.fromFunctionCallId(
|
|
39008
|
+
this.functionCallId
|
|
39009
|
+
);
|
|
39010
|
+
return invocation.awaitOutput(timeout);
|
|
39011
|
+
}
|
|
39012
|
+
/** Cancel a running function call. */
|
|
39013
|
+
async cancel(options = {}) {
|
|
39014
|
+
await client.functionCallCancel({
|
|
39015
|
+
functionCallId: this.functionCallId,
|
|
39016
|
+
terminateContainers: options.terminateContainers
|
|
39017
|
+
});
|
|
39018
|
+
}
|
|
39019
|
+
};
|
|
39020
|
+
|
|
39021
|
+
// src/function.ts
|
|
39022
|
+
import { ClientError as ClientError4, Status as Status4 } from "nice-grpc";
|
|
39023
|
+
var maxObjectSizeBytes = 2 * 1024 * 1024;
|
|
39024
|
+
var maxSystemRetries = 8;
|
|
39025
|
+
var Function_ = class _Function_ {
|
|
39026
|
+
functionId;
|
|
39027
|
+
methodName;
|
|
39028
|
+
/** @ignore */
|
|
39029
|
+
constructor(functionId, methodName) {
|
|
39030
|
+
this.functionId = functionId;
|
|
39031
|
+
this.methodName = methodName;
|
|
39032
|
+
}
|
|
39033
|
+
static async lookup(appName, name, options = {}) {
|
|
39034
|
+
try {
|
|
39035
|
+
const resp = await client.functionGet({
|
|
39036
|
+
appName,
|
|
39037
|
+
objectTag: name,
|
|
39038
|
+
namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
|
|
39039
|
+
environmentName: environmentName(options.environment)
|
|
39040
|
+
});
|
|
39041
|
+
return new _Function_(resp.functionId);
|
|
39042
|
+
} catch (err) {
|
|
39043
|
+
if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
|
|
39044
|
+
throw new NotFoundError(`Function '${appName}/${name}' not found`);
|
|
39045
|
+
throw err;
|
|
39046
|
+
}
|
|
39047
|
+
}
|
|
39048
|
+
// Execute a single input into a remote Function.
|
|
39049
|
+
async remote(args = [], kwargs = {}) {
|
|
39050
|
+
const input = await this.#createInput(args, kwargs);
|
|
39051
|
+
const invocation = await ControlPlaneInvocation.create(
|
|
39052
|
+
this.functionId,
|
|
39053
|
+
input,
|
|
39054
|
+
4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */
|
|
39055
|
+
);
|
|
39056
|
+
let retryCount = 0;
|
|
39057
|
+
while (true) {
|
|
39058
|
+
try {
|
|
39059
|
+
return await invocation.awaitOutput();
|
|
39060
|
+
} catch (err) {
|
|
39061
|
+
if (err instanceof InternalFailure && retryCount <= maxSystemRetries) {
|
|
39062
|
+
await invocation.retry(retryCount);
|
|
39063
|
+
retryCount++;
|
|
39064
|
+
} else {
|
|
39065
|
+
throw err;
|
|
39066
|
+
}
|
|
39067
|
+
}
|
|
39068
|
+
}
|
|
39069
|
+
}
|
|
39070
|
+
// Spawn a single input into a remote function.
|
|
39071
|
+
async spawn(args = [], kwargs = {}) {
|
|
39072
|
+
const input = await this.#createInput(args, kwargs);
|
|
39073
|
+
const invocation = await ControlPlaneInvocation.create(
|
|
39074
|
+
this.functionId,
|
|
39075
|
+
input,
|
|
39076
|
+
3 /* FUNCTION_CALL_INVOCATION_TYPE_ASYNC */
|
|
39077
|
+
);
|
|
39078
|
+
return new FunctionCall(invocation.functionCallId);
|
|
39079
|
+
}
|
|
39080
|
+
async #createInput(args = [], kwargs = {}) {
|
|
39081
|
+
const payload = dumps([args, kwargs]);
|
|
39082
|
+
let argsBlobId = void 0;
|
|
39083
|
+
if (payload.length > maxObjectSizeBytes) {
|
|
39084
|
+
argsBlobId = await blobUpload(payload);
|
|
39085
|
+
}
|
|
39086
|
+
return {
|
|
39087
|
+
args: argsBlobId ? void 0 : payload,
|
|
39088
|
+
argsBlobId,
|
|
39089
|
+
dataFormat: 1 /* DATA_FORMAT_PICKLE */,
|
|
39090
|
+
methodName: this.methodName,
|
|
39091
|
+
finalInput: false
|
|
39092
|
+
// This field isn't specified in the Python client, so it defaults to false.
|
|
39093
|
+
};
|
|
39094
|
+
}
|
|
39095
|
+
};
|
|
38920
39096
|
async function blobUpload(data) {
|
|
38921
39097
|
const contentMd5 = createHash("md5").update(data).digest("base64");
|
|
38922
39098
|
const contentSha256 = createHash("sha256").update(data).digest("base64");
|
|
@@ -38946,30 +39122,6 @@ async function blobUpload(data) {
|
|
|
38946
39122
|
throw new Error("Missing upload URL in BlobCreate response");
|
|
38947
39123
|
}
|
|
38948
39124
|
}
|
|
38949
|
-
async function blobDownload(blobId) {
|
|
38950
|
-
const resp = await client.blobGet({ blobId });
|
|
38951
|
-
const s3resp = await fetch(resp.downloadUrl);
|
|
38952
|
-
if (!s3resp.ok) {
|
|
38953
|
-
throw new Error(`Failed to download blob: ${s3resp.statusText}`);
|
|
38954
|
-
}
|
|
38955
|
-
const buf = await s3resp.arrayBuffer();
|
|
38956
|
-
return new Uint8Array(buf);
|
|
38957
|
-
}
|
|
38958
|
-
function deserializeDataFormat(data, dataFormat) {
|
|
38959
|
-
if (!data) {
|
|
38960
|
-
return null;
|
|
38961
|
-
}
|
|
38962
|
-
switch (dataFormat) {
|
|
38963
|
-
case 1 /* DATA_FORMAT_PICKLE */:
|
|
38964
|
-
return loads(data);
|
|
38965
|
-
case 2 /* DATA_FORMAT_ASGI */:
|
|
38966
|
-
throw new Error("ASGI data format is not supported in Go");
|
|
38967
|
-
case 3 /* DATA_FORMAT_GENERATOR_DONE */:
|
|
38968
|
-
return GeneratorDone.decode(data);
|
|
38969
|
-
default:
|
|
38970
|
-
throw new Error(`Unsupported data format: ${dataFormat}`);
|
|
38971
|
-
}
|
|
38972
|
-
}
|
|
38973
39125
|
|
|
38974
39126
|
// src/cls.ts
|
|
38975
39127
|
var Cls = class _Cls {
|
|
@@ -39010,7 +39162,7 @@ var Cls = class _Cls {
|
|
|
39010
39162
|
}
|
|
39011
39163
|
return new _Cls(serviceFunction.functionId, schema, methodNames);
|
|
39012
39164
|
} catch (err) {
|
|
39013
|
-
if (err instanceof
|
|
39165
|
+
if (err instanceof ClientError5 && err.code === Status5.NOT_FOUND)
|
|
39014
39166
|
throw new NotFoundError(`Class '${appName}/${name}' not found`);
|
|
39015
39167
|
throw err;
|
|
39016
39168
|
}
|
|
@@ -39109,7 +39261,7 @@ var ClsInstance = class {
|
|
|
39109
39261
|
};
|
|
39110
39262
|
|
|
39111
39263
|
// src/queue.ts
|
|
39112
|
-
import { ClientError as
|
|
39264
|
+
import { ClientError as ClientError6, Status as Status6 } from "nice-grpc";
|
|
39113
39265
|
var ephemeralObjectHeartbeatSleep = 3e5;
|
|
39114
39266
|
var queueInitialPutBackoff = 100;
|
|
39115
39267
|
var queueDefaultPartitionTtl = 24 * 3600 * 1e3;
|
|
@@ -39264,7 +39416,7 @@ var Queue = class _Queue {
|
|
|
39264
39416
|
});
|
|
39265
39417
|
break;
|
|
39266
39418
|
} catch (e) {
|
|
39267
|
-
if (e instanceof
|
|
39419
|
+
if (e instanceof ClientError6 && e.code === Status6.RESOURCE_EXHAUSTED) {
|
|
39268
39420
|
delay = Math.min(delay * 2, 3e4);
|
|
39269
39421
|
if (deadline !== void 0) {
|
|
39270
39422
|
const remaining = deadline - Date.now();
|
|
@@ -39370,5 +39522,6 @@ export {
|
|
|
39370
39522
|
QueueEmptyError,
|
|
39371
39523
|
QueueFullError,
|
|
39372
39524
|
RemoteError,
|
|
39373
|
-
Sandbox2 as Sandbox
|
|
39525
|
+
Sandbox2 as Sandbox,
|
|
39526
|
+
Secret
|
|
39374
39527
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Modal client library for JavaScript",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://modal.com/docs",
|
|
7
7
|
"repository": "github:modal-labs/libmodal",
|
|
8
8
|
"bugs": "https://github.com/modal-labs/libmodal/issues",
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"format:check": "prettier --check .",
|
|
30
30
|
"lint": "eslint",
|
|
31
31
|
"prepare": "scripts/gen-proto.sh",
|
|
32
|
-
"test": "vitest"
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"preversion": "(git update-index --really-refresh && git diff-index --quiet HEAD) || (echo 'You must commit all changes before running npm version' && exit 1)",
|
|
34
|
+
"version": "npm run build && git add package.json package-lock.json && git commit -m \"modal-js/v$npm_package_version\" && git tag modal-js/v$npm_package_version",
|
|
35
|
+
"postversion": "git push && git push --tags && npm publish"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"long": "^5.3.1",
|