modal 0.3.0 → 0.3.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/README.md CHANGED
@@ -1,19 +1,25 @@
1
- # modal-js development
1
+ # Modal JavaScript Library
2
2
 
3
- Setup after cloning the repo with submodules:
3
+ [![Version](https://img.shields.io/npm/v/modal.svg)](https://www.npmjs.org/package/modal)
4
+ [![Build Status](https://github.com/modal-labs/libmodal/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/modal-labs/libmodal/actions?query=branch%3Amain)
5
+ [![Downloads](https://img.shields.io/npm/dm/modal.svg)](https://www.npmjs.com/package/modal)
4
6
 
5
- ```bash
6
- npm install
7
- ```
7
+ The [Modal](https://modal.com/) JavaScript SDK allows you to run Modal Functions and Sandboxes from server-side JavaScript applications.
8
8
 
9
- Then run a script with:
9
+ It comes with built-in TypeScript type definitions.
10
10
 
11
- ```bash
12
- node --import tsx path/to/script.ts
13
- ```
11
+ ## Documentation
12
+
13
+ See the [documentation and examples](https://github.com/modal-labs/libmodal?tab=readme-ov-file#javascript-modal-js) on GitHub.
14
14
 
15
- ## gRPC support
15
+ ## Requirements
16
16
 
17
- We're using `nice-grpc` because the `@grpc/grpc-js` library doesn't support promises and is difficult to customize with types.
17
+ Node 22 or higher, in [ES modules](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) mode.
18
18
 
19
- This gRPC library depends on the `protobuf-ts` package, which is not compatible with tree shaking because `ModalClientDefinition` transitively references every type. However, since `modal-js` is a server-side package, having a larger bundled library is not a huge issue.
19
+ ## Installation
20
+
21
+ Install the package with
22
+
23
+ ```bash
24
+ npm install modal
25
+ ```
package/dist/index.d.ts CHANGED
@@ -93,4 +93,25 @@ declare class App {
93
93
  imageFromRegistry(tag: string): Promise<Image>;
94
94
  }
95
95
 
96
- export { App, Image, type LookupOptions, Sandbox, type SandboxCreateOptions, type StdioBehavior, type StreamMode };
96
+ /** Function execution exceeds the allowed time limit. */
97
+ declare class TimeoutError extends Error {
98
+ constructor(message: string);
99
+ }
100
+ /** An error on the Modal server, or a Python exception. */
101
+ declare class RemoteError extends Error {
102
+ constructor(message: string);
103
+ }
104
+ /** A retryable internal error from Modal. */
105
+ declare class InternalFailure extends Error {
106
+ constructor(message: string);
107
+ }
108
+
109
+ /** Represents a deployed Modal Function, which can be invoked remotely. */
110
+ declare class Function_ {
111
+ readonly functionId: string;
112
+ constructor(functionId: string);
113
+ static lookup(appName: string, name: string, options?: LookupOptions): Promise<Function_>;
114
+ remote(args?: any[], kwargs?: Record<string, any>): Promise<any>;
115
+ }
116
+
117
+ export { App, Function_, Image, InternalFailure, type LookupOptions, RemoteError, Sandbox, type SandboxCreateOptions, type StdioBehavior, type StreamMode, TimeoutError };
package/dist/index.js CHANGED
@@ -20247,6 +20247,57 @@ var GPUConfig = {
20247
20247
  return message;
20248
20248
  }
20249
20249
  };
20250
+ function createBaseGeneratorDone() {
20251
+ return { itemsTotal: 0 };
20252
+ }
20253
+ var GeneratorDone = {
20254
+ encode(message, writer = new BinaryWriter()) {
20255
+ if (message.itemsTotal !== 0) {
20256
+ writer.uint32(8).uint64(message.itemsTotal);
20257
+ }
20258
+ return writer;
20259
+ },
20260
+ decode(input, length) {
20261
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
20262
+ let end = length === void 0 ? reader.len : reader.pos + length;
20263
+ const message = createBaseGeneratorDone();
20264
+ while (reader.pos < end) {
20265
+ const tag = reader.uint32();
20266
+ switch (tag >>> 3) {
20267
+ case 1: {
20268
+ if (tag !== 8) {
20269
+ break;
20270
+ }
20271
+ message.itemsTotal = longToNumber(reader.uint64());
20272
+ continue;
20273
+ }
20274
+ }
20275
+ if ((tag & 7) === 4 || tag === 0) {
20276
+ break;
20277
+ }
20278
+ reader.skip(tag & 7);
20279
+ }
20280
+ return message;
20281
+ },
20282
+ fromJSON(object) {
20283
+ return { itemsTotal: isSet3(object.itemsTotal) ? globalThis.Number(object.itemsTotal) : 0 };
20284
+ },
20285
+ toJSON(message) {
20286
+ const obj = {};
20287
+ if (message.itemsTotal !== 0) {
20288
+ obj.itemsTotal = Math.round(message.itemsTotal);
20289
+ }
20290
+ return obj;
20291
+ },
20292
+ create(base) {
20293
+ return GeneratorDone.fromPartial(base ?? {});
20294
+ },
20295
+ fromPartial(object) {
20296
+ const message = createBaseGeneratorDone();
20297
+ message.itemsTotal = object.itemsTotal ?? 0;
20298
+ return message;
20299
+ }
20300
+ };
20250
20301
  function createBaseGenericPayloadType() {
20251
20302
  return { baseType: 0, subTypes: [] };
20252
20303
  }
@@ -36665,13 +36716,19 @@ var timeoutMiddleware = async function* timeoutMiddleware2(call, options) {
36665
36716
  }
36666
36717
  }
36667
36718
  };
36668
- var RETRYABLE_GRPC_STATUS_CODES = [
36719
+ var retryableGrpcStatusCodes = /* @__PURE__ */ new Set([
36669
36720
  Status.DEADLINE_EXCEEDED,
36670
36721
  Status.UNAVAILABLE,
36671
36722
  Status.CANCELLED,
36672
36723
  Status.INTERNAL,
36673
36724
  Status.UNKNOWN
36674
- ];
36725
+ ]);
36726
+ function isRetryableGrpc(error) {
36727
+ if (error instanceof ClientError) {
36728
+ return retryableGrpcStatusCodes.has(error.code);
36729
+ }
36730
+ return false;
36731
+ }
36675
36732
  var sleep = (ms, signal) => new Promise((resolve, reject) => {
36676
36733
  if (signal?.aborted) return reject(signal.reason);
36677
36734
  const t = setTimeout(resolve, ms);
@@ -36698,7 +36755,7 @@ var retryMiddleware = async function* retryMiddleware2(call, options) {
36698
36755
  return yield* call.next(call.request, restOptions);
36699
36756
  }
36700
36757
  const retryableCodes = /* @__PURE__ */ new Set([
36701
- ...RETRYABLE_GRPC_STATUS_CODES,
36758
+ ...retryableGrpcStatusCodes,
36702
36759
  ...additionalStatusCodes
36703
36760
  ]);
36704
36761
  const idempotencyKey = uuidv4();
@@ -36802,81 +36859,112 @@ ${result.exception}`
36802
36859
 
36803
36860
  // src/streams.ts
36804
36861
  function toModalReadStream(stream) {
36805
- return Object.assign(stream, {
36806
- async readText() {
36807
- const reader = stream.getReader();
36808
- try {
36809
- const decoder = new TextDecoder("utf-8");
36810
- const chunks = [];
36811
- while (true) {
36812
- const { value, done } = await reader.read();
36813
- if (value) {
36814
- if (typeof value === "string") chunks.push(value);
36815
- else {
36816
- chunks.push(decoder.decode(value.buffer, { stream: true }));
36817
- }
36818
- }
36819
- if (done) {
36820
- chunks.push(decoder.decode(void 0, { stream: false }));
36821
- break;
36862
+ return Object.assign(stream, readMixin);
36863
+ }
36864
+ function toModalWriteStream(stream) {
36865
+ return Object.assign(stream, writeMixin);
36866
+ }
36867
+ var readMixin = {
36868
+ async readText() {
36869
+ const reader = this.getReader();
36870
+ try {
36871
+ const decoder = new TextDecoder("utf-8");
36872
+ const chunks = [];
36873
+ while (true) {
36874
+ const { value, done } = await reader.read();
36875
+ if (value) {
36876
+ if (typeof value === "string") chunks.push(value);
36877
+ else {
36878
+ chunks.push(decoder.decode(value.buffer, { stream: true }));
36822
36879
  }
36823
36880
  }
36824
- return chunks.join("");
36825
- } finally {
36826
- reader.releaseLock();
36881
+ if (done) {
36882
+ chunks.push(decoder.decode(void 0, { stream: false }));
36883
+ break;
36884
+ }
36827
36885
  }
36828
- },
36829
- async readBytes() {
36830
- const chunks = [];
36831
- const reader = stream.getReader();
36832
- try {
36833
- while (true) {
36834
- const { value, done } = await reader.read();
36835
- if (value) {
36836
- if (typeof value === "string") {
36837
- chunks.push(new TextEncoder().encode(value));
36838
- } else {
36839
- chunks.push(value);
36840
- }
36886
+ return chunks.join("");
36887
+ } finally {
36888
+ reader.releaseLock();
36889
+ }
36890
+ },
36891
+ async readBytes() {
36892
+ const chunks = [];
36893
+ const reader = this.getReader();
36894
+ try {
36895
+ while (true) {
36896
+ const { value, done } = await reader.read();
36897
+ if (value) {
36898
+ if (typeof value === "string") {
36899
+ chunks.push(new TextEncoder().encode(value));
36900
+ } else {
36901
+ chunks.push(value);
36841
36902
  }
36842
- if (done) break;
36843
36903
  }
36844
- } finally {
36845
- reader.releaseLock();
36846
- }
36847
- let totalLength = 0;
36848
- for (const chunk of chunks) {
36849
- totalLength += chunk.length;
36904
+ if (done) break;
36850
36905
  }
36851
- const result = new Uint8Array(totalLength);
36852
- let offset = 0;
36853
- for (const chunk of chunks) {
36854
- result.set(chunk, offset);
36855
- offset += chunk.length;
36856
- }
36857
- return result;
36906
+ } finally {
36907
+ reader.releaseLock();
36858
36908
  }
36859
- });
36860
- }
36861
- function toModalWriteStream(stream) {
36862
- return Object.assign(stream, {
36863
- async writeText(text) {
36864
- const writer = stream.getWriter();
36865
- try {
36866
- await writer.write(text);
36867
- } finally {
36868
- writer.releaseLock();
36909
+ let totalLength = 0;
36910
+ for (const chunk of chunks) {
36911
+ totalLength += chunk.length;
36912
+ }
36913
+ const result = new Uint8Array(totalLength);
36914
+ let offset = 0;
36915
+ for (const chunk of chunks) {
36916
+ result.set(chunk, offset);
36917
+ offset += chunk.length;
36918
+ }
36919
+ return result;
36920
+ }
36921
+ };
36922
+ var writeMixin = {
36923
+ async writeText(text) {
36924
+ const writer = this.getWriter();
36925
+ try {
36926
+ await writer.write(text);
36927
+ } finally {
36928
+ writer.releaseLock();
36929
+ }
36930
+ },
36931
+ async writeBytes(bytes) {
36932
+ const writer = this.getWriter();
36933
+ try {
36934
+ await writer.write(bytes);
36935
+ } finally {
36936
+ writer.releaseLock();
36937
+ }
36938
+ }
36939
+ };
36940
+ function streamConsumingIter(iterable) {
36941
+ const iter = iterable[Symbol.asyncIterator]();
36942
+ return new ReadableStream(
36943
+ {
36944
+ async pull(controller) {
36945
+ const { done, value } = await iter.next();
36946
+ if (value) {
36947
+ controller.enqueue(value);
36948
+ }
36949
+ if (done) {
36950
+ controller.close();
36951
+ }
36952
+ },
36953
+ async cancel() {
36954
+ consumeIterator(iter);
36869
36955
  }
36870
36956
  },
36871
- async writeBytes(bytes) {
36872
- const writer = stream.getWriter();
36873
- try {
36874
- await writer.write(bytes);
36875
- } finally {
36876
- writer.releaseLock();
36877
- }
36878
- }
36879
- });
36957
+ new ByteLengthQueuingStrategy({
36958
+ highWaterMark: 64 * 1024
36959
+ // 64 KiB
36960
+ })
36961
+ );
36962
+ }
36963
+ async function consumeIterator(iter) {
36964
+ while (true) {
36965
+ const { done } = await iter.next();
36966
+ if (done) break;
36967
+ }
36880
36968
  }
36881
36969
 
36882
36970
  // src/sandbox.ts
@@ -36890,14 +36978,14 @@ var Sandbox2 = class {
36890
36978
  this.sandboxId = sandboxId;
36891
36979
  this.stdin = toModalWriteStream(inputStreamSb(sandboxId));
36892
36980
  this.stdout = toModalReadStream(
36893
- ReadableStream.from(
36981
+ streamConsumingIter(
36894
36982
  outputStreamSb(sandboxId, 1 /* FILE_DESCRIPTOR_STDOUT */)
36895
- )
36983
+ ).pipeThrough(new TextDecoderStream())
36896
36984
  );
36897
36985
  this.stderr = toModalReadStream(
36898
- ReadableStream.from(
36986
+ streamConsumingIter(
36899
36987
  outputStreamSb(sandboxId, 2 /* FILE_DESCRIPTOR_STDERR */)
36900
- )
36988
+ ).pipeThrough(new TextDecoderStream())
36901
36989
  );
36902
36990
  }
36903
36991
  async exec(command, options) {
@@ -36951,12 +37039,20 @@ var ContainerProcess = class {
36951
37039
  const stderr = options?.stderr ?? "pipe";
36952
37040
  this.#execId = execId;
36953
37041
  this.stdin = toModalWriteStream(inputStreamCp(execId));
36954
- const stdoutStream = ReadableStream.from(
36955
- stdout === "pipe" ? outputStreamCp(execId, 1 /* FILE_DESCRIPTOR_STDOUT */) : []
37042
+ let stdoutStream = streamConsumingIter(
37043
+ outputStreamCp(execId, 1 /* FILE_DESCRIPTOR_STDOUT */)
36956
37044
  );
36957
- const stderrStream = ReadableStream.from(
36958
- stderr === "pipe" ? outputStreamCp(execId, 2 /* FILE_DESCRIPTOR_STDERR */) : []
37045
+ if (stdout === "ignore") {
37046
+ stdoutStream.cancel();
37047
+ stdoutStream = ReadableStream.from([]);
37048
+ }
37049
+ let stderrStream = streamConsumingIter(
37050
+ outputStreamCp(execId, 2 /* FILE_DESCRIPTOR_STDERR */)
36959
37051
  );
37052
+ if (stderr === "ignore") {
37053
+ stderrStream.cancel();
37054
+ stderrStream = ReadableStream.from([]);
37055
+ }
36960
37056
  if (mode === "text") {
36961
37057
  this.stdout = toModalReadStream(
36962
37058
  stdoutStream.pipeThrough(new TextDecoderStream())
@@ -36985,7 +37081,7 @@ var ContainerProcess = class {
36985
37081
  async function* outputStreamSb(sandboxId, fileDescriptor) {
36986
37082
  let lastIndex = "0-0";
36987
37083
  let completed = false;
36988
- let retriesRemaining = 10;
37084
+ let retries = 10;
36989
37085
  while (!completed) {
36990
37086
  try {
36991
37087
  const outputIterator = client.sandboxGetLogs({
@@ -36996,25 +37092,22 @@ async function* outputStreamSb(sandboxId, fileDescriptor) {
36996
37092
  });
36997
37093
  for await (const batch of outputIterator) {
36998
37094
  lastIndex = batch.entryId;
36999
- yield* batch.items.map((item) => item.data);
37095
+ yield* batch.items.map((item) => new TextEncoder().encode(item.data));
37000
37096
  if (batch.eof) {
37001
37097
  completed = true;
37002
37098
  break;
37003
37099
  }
37004
37100
  }
37005
37101
  } catch (error) {
37006
- if (retriesRemaining > 0) {
37007
- retriesRemaining--;
37008
- } else {
37009
- throw error;
37010
- }
37102
+ if (isRetryableGrpc(error) && retries > 0) retries--;
37103
+ else throw error;
37011
37104
  }
37012
37105
  }
37013
37106
  }
37014
37107
  async function* outputStreamCp(execId, fileDescriptor) {
37015
37108
  let lastIndex = 0;
37016
37109
  let completed = false;
37017
- let retriesRemaining = 10;
37110
+ let retries = 10;
37018
37111
  while (!completed) {
37019
37112
  try {
37020
37113
  const outputIterator = client.containerExecGetOutput({
@@ -37033,11 +37126,8 @@ async function* outputStreamCp(execId, fileDescriptor) {
37033
37126
  }
37034
37127
  }
37035
37128
  } catch (error) {
37036
- if (retriesRemaining > 0) {
37037
- retriesRemaining--;
37038
- } else {
37039
- throw error;
37040
- }
37129
+ if (isRetryableGrpc(error) && retries > 0) retries--;
37130
+ else throw error;
37041
37131
  }
37042
37132
  }
37043
37133
  }
@@ -37128,8 +37218,432 @@ var App = class _App {
37128
37218
  return await fromRegistryInternal(this.appId, tag);
37129
37219
  }
37130
37220
  };
37221
+
37222
+ // src/errors.ts
37223
+ var TimeoutError = class extends Error {
37224
+ constructor(message) {
37225
+ super(message);
37226
+ this.name = "TimeoutError";
37227
+ }
37228
+ };
37229
+ var RemoteError = class extends Error {
37230
+ constructor(message) {
37231
+ super(message);
37232
+ this.name = "RemoteError";
37233
+ }
37234
+ };
37235
+ var InternalFailure = class extends Error {
37236
+ constructor(message) {
37237
+ super(message);
37238
+ this.name = "InternalFailure";
37239
+ }
37240
+ };
37241
+
37242
+ // src/pickle.ts
37243
+ var PickleError = class extends Error {
37244
+ constructor(message) {
37245
+ super(message);
37246
+ this.name = "PickleError";
37247
+ }
37248
+ };
37249
+ var Writer = class {
37250
+ out = [];
37251
+ byte(b) {
37252
+ this.out.push(b & 255);
37253
+ }
37254
+ bytes(arr) {
37255
+ for (const b of arr) this.byte(b);
37256
+ }
37257
+ uint32LE(x) {
37258
+ this.byte(x);
37259
+ this.byte(x >>> 8);
37260
+ this.byte(x >>> 16);
37261
+ this.byte(x >>> 24);
37262
+ }
37263
+ uint64LE(n) {
37264
+ let v = BigInt(n);
37265
+ for (let i = 0; i < 8; i++) {
37266
+ this.byte(Number(v & 0xffn));
37267
+ v >>= 8n;
37268
+ }
37269
+ }
37270
+ float64BE(v) {
37271
+ const dv = new DataView(new ArrayBuffer(8));
37272
+ dv.setFloat64(0, v, false);
37273
+ this.bytes(new Uint8Array(dv.buffer));
37274
+ }
37275
+ toUint8() {
37276
+ return new Uint8Array(this.out);
37277
+ }
37278
+ };
37279
+ var Reader = class {
37280
+ constructor(buf, pos = 0) {
37281
+ this.buf = buf;
37282
+ this.pos = pos;
37283
+ }
37284
+ eof() {
37285
+ return this.pos >= this.buf.length;
37286
+ }
37287
+ byte() {
37288
+ return this.buf[this.pos++];
37289
+ }
37290
+ take(n) {
37291
+ const s = this.buf.subarray(this.pos, this.pos + n);
37292
+ this.pos += n;
37293
+ return s;
37294
+ }
37295
+ uint32LE() {
37296
+ const b0 = this.byte(), b1 = this.byte(), b2 = this.byte(), b3 = this.byte();
37297
+ return b0 | b1 << 8 | b2 << 16 | b3 << 24;
37298
+ }
37299
+ uint64LE() {
37300
+ const lo = this.uint32LE() >>> 0;
37301
+ const hi = this.uint32LE() >>> 0;
37302
+ return hi * 2 ** 32 + lo;
37303
+ }
37304
+ float64BE() {
37305
+ const v = new DataView(
37306
+ this.buf.buffer,
37307
+ this.buf.byteOffset + this.pos,
37308
+ 8
37309
+ ).getFloat64(0, false);
37310
+ this.pos += 8;
37311
+ return v;
37312
+ }
37313
+ };
37314
+ function encodeValue(val, w, proto) {
37315
+ if (val === null || val === void 0) {
37316
+ w.byte(78 /* NONE */);
37317
+ return;
37318
+ }
37319
+ if (typeof val === "boolean") {
37320
+ w.byte(val ? 136 /* NEWTRUE */ : 137 /* NEWFALSE */);
37321
+ return;
37322
+ }
37323
+ if (typeof val === "number") {
37324
+ if (Number.isInteger(val)) {
37325
+ if (val >= 0 && val <= 255) {
37326
+ w.byte(75 /* BININT1 */);
37327
+ w.byte(val);
37328
+ } else if (val >= -32768 && val <= 32767) {
37329
+ w.byte(77 /* BININT2 */);
37330
+ w.byte(val & 255);
37331
+ w.byte(val >> 8 & 255);
37332
+ } else {
37333
+ w.byte(74 /* BININT4 */);
37334
+ w.uint32LE(val >>> 0);
37335
+ }
37336
+ } else {
37337
+ w.byte(71 /* BINFLOAT */);
37338
+ w.float64BE(val);
37339
+ }
37340
+ maybeMemoize(w, proto);
37341
+ return;
37342
+ }
37343
+ if (typeof val === "string") {
37344
+ const utf8 = new TextEncoder().encode(val);
37345
+ if (proto >= 4 && utf8.length < 256) {
37346
+ w.byte(140 /* SHORT_BINUNICODE */);
37347
+ w.byte(utf8.length);
37348
+ } else if (proto >= 4 && utf8.length > 4294967295) {
37349
+ w.byte(138 /* BINUNICODE8 */);
37350
+ w.uint64LE(utf8.length);
37351
+ } else {
37352
+ w.byte(88 /* BINUNICODE */);
37353
+ w.uint32LE(utf8.length);
37354
+ }
37355
+ w.bytes(utf8);
37356
+ maybeMemoize(w, proto);
37357
+ return;
37358
+ }
37359
+ if (val instanceof Uint8Array) {
37360
+ const len = val.length;
37361
+ if (proto >= 4 && len < 256) {
37362
+ w.byte(142 /* SHORT_BINBYTES */);
37363
+ w.byte(len);
37364
+ } else if (proto >= 4 && len > 4294967295) {
37365
+ w.byte(141 /* BINBYTES8 */);
37366
+ w.uint64LE(len);
37367
+ } else {
37368
+ w.byte(66 /* BINBYTES */);
37369
+ w.uint32LE(len);
37370
+ }
37371
+ w.bytes(val);
37372
+ maybeMemoize(w, proto);
37373
+ return;
37374
+ }
37375
+ if (Array.isArray(val)) {
37376
+ w.byte(93 /* EMPTY_LIST */);
37377
+ maybeMemoize(w, proto);
37378
+ for (const item of val) {
37379
+ encodeValue(item, w, proto);
37380
+ w.byte(97 /* APPEND */);
37381
+ }
37382
+ return;
37383
+ }
37384
+ if (typeof val === "object") {
37385
+ w.byte(125 /* EMPTY_DICT */);
37386
+ maybeMemoize(w, proto);
37387
+ for (const [k, v] of Object.entries(val)) {
37388
+ encodeValue(k, w, proto);
37389
+ encodeValue(v, w, proto);
37390
+ w.byte(115 /* SETITEM */);
37391
+ }
37392
+ return;
37393
+ }
37394
+ throw new PickleError(`Unsupported type in dumps(): ${typeof val}`);
37395
+ }
37396
+ function maybeMemoize(w, proto) {
37397
+ if (proto >= 4) {
37398
+ w.byte(148 /* MEMOIZE */);
37399
+ }
37400
+ }
37401
+ function dumps(obj, protocol = 4) {
37402
+ if (![3, 4, 5].includes(protocol))
37403
+ throw new PickleError("Protocol must be 3, 4, or 5");
37404
+ const w = new Writer();
37405
+ w.byte(128 /* PROTO */);
37406
+ w.byte(protocol);
37407
+ if (protocol === 5) {
37408
+ w.byte(149 /* FRAME */);
37409
+ w.uint64LE(0);
37410
+ }
37411
+ encodeValue(obj, w, protocol);
37412
+ w.byte(46 /* STOP */);
37413
+ return w.toUint8();
37414
+ }
37415
+ function loads(buf) {
37416
+ const r = new Reader(buf);
37417
+ const op0 = r.byte();
37418
+ if (op0 !== 128 /* PROTO */) throw new PickleError("pickle missing PROTO header");
37419
+ const proto = r.byte();
37420
+ if (!(proto === 3 || proto === 4 || proto === 5))
37421
+ throw new PickleError(`Unsupported protocol ${proto}`);
37422
+ const stack = [];
37423
+ const memo = [];
37424
+ const tdec = new TextDecoder();
37425
+ function push(v) {
37426
+ stack.push(v);
37427
+ }
37428
+ function pop() {
37429
+ return stack.pop();
37430
+ }
37431
+ if (proto === 5 && buf[r["pos"]] === 149 /* FRAME */) {
37432
+ r.byte();
37433
+ const size = r.uint64LE();
37434
+ void size;
37435
+ }
37436
+ while (!r.eof()) {
37437
+ const op = r.byte();
37438
+ switch (op) {
37439
+ case 46 /* STOP */:
37440
+ return stack.pop();
37441
+ case 78 /* NONE */:
37442
+ push(null);
37443
+ break;
37444
+ case 136 /* NEWTRUE */:
37445
+ push(true);
37446
+ break;
37447
+ case 137 /* NEWFALSE */:
37448
+ push(false);
37449
+ break;
37450
+ case 75 /* BININT1 */:
37451
+ push(r.byte());
37452
+ break;
37453
+ case 77 /* BININT2 */: {
37454
+ const lo = r.byte(), hi = r.byte();
37455
+ const n = hi << 8 | lo;
37456
+ push(n & 32768 ? n - 65536 : n);
37457
+ break;
37458
+ }
37459
+ case 74 /* BININT4 */: {
37460
+ const n = r.uint32LE();
37461
+ push(n >>> 31 ? n - 4294967296 : n);
37462
+ break;
37463
+ }
37464
+ case 71 /* BINFLOAT */:
37465
+ push(r.float64BE());
37466
+ break;
37467
+ case 140 /* SHORT_BINUNICODE */: {
37468
+ const n = r.byte();
37469
+ push(tdec.decode(r.take(n)));
37470
+ break;
37471
+ }
37472
+ case 88 /* BINUNICODE */: {
37473
+ const n = r.uint32LE();
37474
+ push(tdec.decode(r.take(n)));
37475
+ break;
37476
+ }
37477
+ case 138 /* BINUNICODE8 */: {
37478
+ const n = r.uint64LE();
37479
+ push(tdec.decode(r.take(n)));
37480
+ break;
37481
+ }
37482
+ case 142 /* SHORT_BINBYTES */: {
37483
+ const n = r.byte();
37484
+ push(r.take(n));
37485
+ break;
37486
+ }
37487
+ case 66 /* BINBYTES */: {
37488
+ const n = r.uint32LE();
37489
+ push(r.take(n));
37490
+ break;
37491
+ }
37492
+ case 141 /* BINBYTES8 */: {
37493
+ const n = r.uint64LE();
37494
+ push(r.take(n));
37495
+ break;
37496
+ }
37497
+ case 93 /* EMPTY_LIST */:
37498
+ push([]);
37499
+ break;
37500
+ case 97 /* APPEND */: {
37501
+ const v = pop();
37502
+ const lst = pop();
37503
+ lst.push(v);
37504
+ push(lst);
37505
+ break;
37506
+ }
37507
+ case 125 /* EMPTY_DICT */:
37508
+ push({});
37509
+ break;
37510
+ case 115 /* SETITEM */: {
37511
+ const v = pop(), k = pop(), d = pop();
37512
+ d[k] = v;
37513
+ push(d);
37514
+ break;
37515
+ }
37516
+ // Memo handling ----------------------------------------
37517
+ case 148 /* MEMOIZE */:
37518
+ memo.push(stack[stack.length - 1]);
37519
+ break;
37520
+ case 113 /* BINPUT */:
37521
+ memo[r.byte()] = stack[stack.length - 1];
37522
+ break;
37523
+ case 114 /* LONG_BINPUT */:
37524
+ memo[r.uint32LE()] = stack[stack.length - 1];
37525
+ break;
37526
+ case 104 /* BINGET */:
37527
+ push(memo[r.byte()]);
37528
+ break;
37529
+ case 106 /* LONG_BINGET */:
37530
+ push(memo[r.uint32LE()]);
37531
+ break;
37532
+ case 149 /* FRAME */: {
37533
+ const _size = r.uint64LE();
37534
+ break;
37535
+ }
37536
+ default:
37537
+ throw new PickleError(`Unsupported opcode 0x${op.toString(16)}`);
37538
+ }
37539
+ }
37540
+ throw new PickleError("pickle stream ended without STOP");
37541
+ }
37542
+
37543
+ // src/function.ts
37544
+ function timeNow() {
37545
+ return Date.now() / 1e3;
37546
+ }
37547
+ var Function_ = class _Function_ {
37548
+ functionId;
37549
+ constructor(functionId) {
37550
+ this.functionId = functionId;
37551
+ }
37552
+ static async lookup(appName, name, options = {}) {
37553
+ const resp = await client.functionGet({
37554
+ appName,
37555
+ objectTag: name,
37556
+ namespace: 1 /* DEPLOYMENT_NAMESPACE_WORKSPACE */,
37557
+ environmentName: environmentName(options.environment)
37558
+ });
37559
+ return new _Function_(resp.functionId);
37560
+ }
37561
+ // Execute a single input into a remote Function.
37562
+ async remote(args = [], kwargs = {}) {
37563
+ const payload = dumps([args, kwargs]);
37564
+ const functionInputs = [
37565
+ {
37566
+ idx: 0,
37567
+ input: {
37568
+ args: payload,
37569
+ dataFormat: 1 /* DATA_FORMAT_PICKLE */
37570
+ }
37571
+ }
37572
+ ];
37573
+ const functionMapResponse = await client.functionMap({
37574
+ functionId: this.functionId,
37575
+ functionCallType: 1 /* FUNCTION_CALL_TYPE_UNARY */,
37576
+ functionCallInvocationType: 4 /* FUNCTION_CALL_INVOCATION_TYPE_SYNC */,
37577
+ pipelinedInputs: functionInputs
37578
+ });
37579
+ while (true) {
37580
+ const response = await client.functionGetOutputs({
37581
+ functionCallId: functionMapResponse.functionCallId,
37582
+ maxValues: 1,
37583
+ timeout: 55,
37584
+ lastEntryId: "0-0",
37585
+ clearOnSuccess: true,
37586
+ requestedAt: timeNow()
37587
+ });
37588
+ const outputs = response.outputs;
37589
+ if (outputs.length > 0) {
37590
+ return await processResult(outputs[0].result, outputs[0].dataFormat);
37591
+ }
37592
+ }
37593
+ }
37594
+ };
37595
+ async function processResult(result, dataFormat) {
37596
+ if (!result) {
37597
+ throw new Error("Received null result from invocation");
37598
+ }
37599
+ let data = new Uint8Array();
37600
+ if (result.data !== void 0) {
37601
+ data = result.data;
37602
+ } else if (result.dataBlobId) {
37603
+ data = await blobDownload(result.dataBlobId);
37604
+ }
37605
+ switch (result.status) {
37606
+ case 4 /* GENERIC_STATUS_TIMEOUT */:
37607
+ throw new TimeoutError(`Timeout: ${result.exception}`);
37608
+ case 6 /* GENERIC_STATUS_INTERNAL_FAILURE */:
37609
+ throw new InternalFailure(`Internal failure: ${result.exception}`);
37610
+ case 1 /* GENERIC_STATUS_SUCCESS */:
37611
+ break;
37612
+ default:
37613
+ throw new RemoteError(`Remote error: ${result.exception}`);
37614
+ }
37615
+ return deserializeDataFormat(result.data, dataFormat);
37616
+ }
37617
+ async function blobDownload(blobId) {
37618
+ const resp = await client.blobGet({ blobId });
37619
+ const s3resp = await fetch(resp.downloadUrl);
37620
+ if (!s3resp.ok) {
37621
+ throw new Error(`Failed to download blob: ${s3resp.statusText}`);
37622
+ }
37623
+ const buf = await s3resp.arrayBuffer();
37624
+ return new Uint8Array(buf);
37625
+ }
37626
+ function deserializeDataFormat(data, dataFormat) {
37627
+ if (!data) {
37628
+ return null;
37629
+ }
37630
+ switch (dataFormat) {
37631
+ case 1 /* DATA_FORMAT_PICKLE */:
37632
+ return loads(data);
37633
+ case 2 /* DATA_FORMAT_ASGI */:
37634
+ throw new Error("ASGI data format is not supported in Go");
37635
+ case 3 /* DATA_FORMAT_GENERATOR_DONE */:
37636
+ return GeneratorDone.decode(data);
37637
+ default:
37638
+ throw new Error(`Unsupported data format: ${dataFormat}`);
37639
+ }
37640
+ }
37131
37641
  export {
37132
37642
  App,
37643
+ Function_,
37133
37644
  Image2 as Image,
37134
- Sandbox2 as Sandbox
37645
+ InternalFailure,
37646
+ RemoteError,
37647
+ Sandbox2 as Sandbox,
37648
+ TimeoutError
37135
37649
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modal",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Modal client library for JavaScript",
5
5
  "license": "MIT",
6
6
  "homepage": "https://modal.com/docs",