modal 0.3.6 → 0.3.7

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.d.ts CHANGED
@@ -1,5 +1,55 @@
1
1
  import { BinaryWriter, BinaryReader } from '@bufbuild/protobuf/wire';
2
2
 
3
+ declare enum ParameterType {
4
+ PARAM_TYPE_UNSPECIFIED = 0,
5
+ PARAM_TYPE_STRING = 1,
6
+ PARAM_TYPE_INT = 2,
7
+ /** PARAM_TYPE_PICKLE - currently unused */
8
+ PARAM_TYPE_PICKLE = 3,
9
+ PARAM_TYPE_BYTES = 4,
10
+ /** PARAM_TYPE_UNKNOWN - used in schemas to signify unrecognized or un-annotated types */
11
+ PARAM_TYPE_UNKNOWN = 5,
12
+ PARAM_TYPE_LIST = 6,
13
+ PARAM_TYPE_DICT = 7,
14
+ PARAM_TYPE_NONE = 8,
15
+ PARAM_TYPE_BOOL = 9,
16
+ UNRECOGNIZED = -1
17
+ }
18
+ /** TODO: rename into NamedPayloadType or similar */
19
+ interface ClassParameterSpec {
20
+ name: string;
21
+ /** TODO: deprecate - use full_type instead */
22
+ type: ParameterType;
23
+ hasDefault: boolean;
24
+ /** Default *values* are only registered for class parameters */
25
+ stringDefault?: string | undefined;
26
+ intDefault?: number | undefined;
27
+ pickleDefault?: Uint8Array | undefined;
28
+ bytesDefault?: Uint8Array | undefined;
29
+ boolDefault?: boolean | undefined;
30
+ /** supersedes `type` */
31
+ fullType: GenericPayloadType | undefined;
32
+ }
33
+ declare const ClassParameterSpec: MessageFns<ClassParameterSpec>;
34
+ interface GenericPayloadType {
35
+ baseType: ParameterType;
36
+ /** sub-type for generic types like lists */
37
+ subTypes: GenericPayloadType[];
38
+ }
39
+ declare const GenericPayloadType: MessageFns<GenericPayloadType>;
40
+ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
41
+ type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
42
+ [K in keyof T]?: DeepPartial<T[K]>;
43
+ } : Partial<T>;
44
+ interface MessageFns<T> {
45
+ encode(message: T, writer?: BinaryWriter): BinaryWriter;
46
+ decode(input: BinaryReader | Uint8Array, length?: number): T;
47
+ fromJSON(object: any): T;
48
+ toJSON(message: T): unknown;
49
+ create(base?: DeepPartial<T>): T;
50
+ fromPartial(object: DeepPartial<T>): T;
51
+ }
52
+
3
53
  /** A container image, used for starting sandboxes. */
4
54
  declare class Image {
5
55
  readonly imageId: string;
@@ -92,6 +142,20 @@ declare class ContainerProcess<R extends string | Uint8Array = any> {
92
142
  wait(): Promise<number>;
93
143
  }
94
144
 
145
+ /** Options for `Secret.fromName()`. */
146
+ type SecretFromNameOptions = {
147
+ environment?: string;
148
+ requiredKeys?: string[];
149
+ };
150
+ /** Secrets provide a dictionary of environment variables for images. */
151
+ declare class Secret {
152
+ readonly secretId: string;
153
+ /** @ignore */
154
+ constructor(secretId: string);
155
+ /** Reference a Secret by its name. */
156
+ static fromName(name: string, options?: SecretFromNameOptions): Promise<Secret>;
157
+ }
158
+
95
159
  /** Options for functions that find deployed Modal objects. */
96
160
  type LookupOptions = {
97
161
  environment?: string;
@@ -128,56 +192,7 @@ declare class App {
128
192
  static lookup(name: string, options?: LookupOptions): Promise<App>;
129
193
  createSandbox(image: Image, options?: SandboxCreateOptions): Promise<Sandbox>;
130
194
  imageFromRegistry(tag: string): Promise<Image>;
131
- }
132
-
133
- declare enum ParameterType {
134
- PARAM_TYPE_UNSPECIFIED = 0,
135
- PARAM_TYPE_STRING = 1,
136
- PARAM_TYPE_INT = 2,
137
- /** PARAM_TYPE_PICKLE - currently unused */
138
- PARAM_TYPE_PICKLE = 3,
139
- PARAM_TYPE_BYTES = 4,
140
- /** PARAM_TYPE_UNKNOWN - used in schemas to signify unrecognized or un-annotated types */
141
- PARAM_TYPE_UNKNOWN = 5,
142
- PARAM_TYPE_LIST = 6,
143
- PARAM_TYPE_DICT = 7,
144
- PARAM_TYPE_NONE = 8,
145
- PARAM_TYPE_BOOL = 9,
146
- UNRECOGNIZED = -1
147
- }
148
- /** TODO: rename into NamedPayloadType or similar */
149
- interface ClassParameterSpec {
150
- name: string;
151
- /** TODO: deprecate - use full_type instead */
152
- type: ParameterType;
153
- hasDefault: boolean;
154
- /** Default *values* are only registered for class parameters */
155
- stringDefault?: string | undefined;
156
- intDefault?: number | undefined;
157
- pickleDefault?: Uint8Array | undefined;
158
- bytesDefault?: Uint8Array | undefined;
159
- boolDefault?: boolean | undefined;
160
- /** supersedes `type` */
161
- fullType: GenericPayloadType | undefined;
162
- }
163
- declare const ClassParameterSpec: MessageFns<ClassParameterSpec>;
164
- interface GenericPayloadType {
165
- baseType: ParameterType;
166
- /** sub-type for generic types like lists */
167
- subTypes: GenericPayloadType[];
168
- }
169
- declare const GenericPayloadType: MessageFns<GenericPayloadType>;
170
- type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
171
- type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
172
- [K in keyof T]?: DeepPartial<T[K]>;
173
- } : Partial<T>;
174
- interface MessageFns<T> {
175
- encode(message: T, writer?: BinaryWriter): BinaryWriter;
176
- decode(input: BinaryReader | Uint8Array, length?: number): T;
177
- fromJSON(object: any): T;
178
- toJSON(message: T): unknown;
179
- create(base?: DeepPartial<T>): T;
180
- fromPartial(object: DeepPartial<T>): T;
195
+ imageFromAwsEcr(tag: string, secret: Secret): Promise<Image>;
181
196
  }
182
197
 
183
198
  /** Options for `FunctionCall.get()`. */
@@ -362,4 +377,4 @@ declare class Queue {
362
377
  iterate(options?: QueueIterateOptions): AsyncGenerator<any, void, unknown>;
363
378
  }
364
379
 
365
- export { App, Cls, ClsInstance, ContainerProcess, type DeleteOptions, type EphemeralOptions, type ExecOptions, FunctionCall, type FunctionCallCancelOptions, type FunctionCallGetOptions, FunctionTimeoutError, Function_, Image, InternalFailure, InvalidError, type LookupOptions, type ModalReadStream, type ModalWriteStream, NotFoundError, Queue, type QueueClearOptions, QueueEmptyError, QueueFullError, type QueueGetOptions, type QueueIterateOptions, type QueueLenOptions, type QueuePutOptions, RemoteError, Sandbox, type SandboxCreateOptions, type StdioBehavior, type StreamMode };
380
+ export { App, Cls, ClsInstance, ContainerProcess, type DeleteOptions, type EphemeralOptions, type ExecOptions, FunctionCall, type FunctionCallCancelOptions, type FunctionCallGetOptions, FunctionTimeoutError, Function_, Image, InternalFailure, InvalidError, type LookupOptions, type ModalReadStream, type ModalWriteStream, NotFoundError, Queue, type QueueClearOptions, QueueEmptyError, QueueFullError, type QueueGetOptions, type QueueIterateOptions, type QueueLenOptions, type QueuePutOptions, RemoteError, Sandbox, type SandboxCreateOptions, Secret, type SecretFromNameOptions, type StdioBehavior, type StreamMode };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/app.ts
2
- import { ClientError as ClientError2, Status as Status2 } from "nice-grpc";
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() {
@@ -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: "2024.10"
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 ClientError2 && err.code === Status2.NOT_FOUND)
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,10 +38485,22 @@ 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 ClientError4, Status as Status4 } from "nice-grpc";
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";
@@ -38548,6 +38592,15 @@ var Reader = class {
38548
38592
  const hi = this.uint32LE() >>> 0;
38549
38593
  return hi * 2 ** 32 + lo;
38550
38594
  }
38595
+ int32LE() {
38596
+ const v = new DataView(
38597
+ this.buf.buffer,
38598
+ this.buf.byteOffset + this.pos,
38599
+ 4
38600
+ ).getInt32(0, true);
38601
+ this.pos += 4;
38602
+ return v;
38603
+ }
38551
38604
  float64BE() {
38552
38605
  const v = new DataView(
38553
38606
  this.buf.buffer,
@@ -38680,6 +38733,7 @@ function loads(buf) {
38680
38733
  const size = r.uint64LE();
38681
38734
  void size;
38682
38735
  }
38736
+ const MARK = Symbol("pickle-mark");
38683
38737
  while (!r.eof()) {
38684
38738
  const op = r.byte();
38685
38739
  switch (op) {
@@ -38704,8 +38758,7 @@ function loads(buf) {
38704
38758
  break;
38705
38759
  }
38706
38760
  case 74 /* BININT4 */: {
38707
- const n = r.uint32LE();
38708
- push(n >>> 31 ? n - 4294967296 : n);
38761
+ push(r.int32LE());
38709
38762
  break;
38710
38763
  }
38711
38764
  case 71 /* BINFLOAT */:
@@ -38780,6 +38833,43 @@ function loads(buf) {
38780
38833
  const _size = r.uint64LE();
38781
38834
  break;
38782
38835
  }
38836
+ case 40 /* MARK */:
38837
+ push(MARK);
38838
+ break;
38839
+ case 101 /* APPENDS */: {
38840
+ const markIndex = stack.lastIndexOf(MARK);
38841
+ if (markIndex === -1) {
38842
+ throw new PickleError("APPENDS without MARK");
38843
+ }
38844
+ const lst = stack[markIndex - 1];
38845
+ if (!Array.isArray(lst)) {
38846
+ throw new PickleError("APPENDS expects a list below MARK");
38847
+ }
38848
+ const items = stack.slice(markIndex + 1);
38849
+ lst.push(...items);
38850
+ stack.length = markIndex - 1;
38851
+ push(lst);
38852
+ break;
38853
+ }
38854
+ case 117 /* SETITEMS */: {
38855
+ const markIndex = stack.lastIndexOf(MARK);
38856
+ if (markIndex === -1) {
38857
+ throw new PickleError("SETITEMS without MARK");
38858
+ }
38859
+ const d = stack[markIndex - 1];
38860
+ if (typeof d !== "object" || d === null || Array.isArray(d)) {
38861
+ throw new PickleError("SETITEMS expects a dict below MARK");
38862
+ }
38863
+ const items = stack.slice(markIndex + 1);
38864
+ for (let i = 0; i < items.length; i += 2) {
38865
+ if (i + 1 < items.length) {
38866
+ d[items[i]] = items[i + 1];
38867
+ }
38868
+ }
38869
+ stack.length = markIndex - 1;
38870
+ push(d);
38871
+ break;
38872
+ }
38783
38873
  default:
38784
38874
  throw new PickleError(`Unsupported opcode 0x${op.toString(16)}`);
38785
38875
  }
@@ -38788,7 +38878,7 @@ function loads(buf) {
38788
38878
  }
38789
38879
 
38790
38880
  // src/function.ts
38791
- import { ClientError as ClientError3, Status as Status3 } from "nice-grpc";
38881
+ import { ClientError as ClientError4, Status as Status4 } from "nice-grpc";
38792
38882
  var maxObjectSizeBytes = 2 * 1024 * 1024;
38793
38883
  var outputsTimeout = 55 * 1e3;
38794
38884
  function timeNowSeconds() {
@@ -38812,7 +38902,7 @@ var Function_ = class _Function_ {
38812
38902
  });
38813
38903
  return new _Function_(resp.functionId);
38814
38904
  } catch (err) {
38815
- if (err instanceof ClientError3 && err.code === Status3.NOT_FOUND)
38905
+ if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
38816
38906
  throw new NotFoundError(`Function '${appName}/${name}' not found`);
38817
38907
  throw err;
38818
38908
  }
@@ -39010,7 +39100,7 @@ var Cls = class _Cls {
39010
39100
  }
39011
39101
  return new _Cls(serviceFunction.functionId, schema, methodNames);
39012
39102
  } catch (err) {
39013
- if (err instanceof ClientError4 && err.code === Status4.NOT_FOUND)
39103
+ if (err instanceof ClientError5 && err.code === Status5.NOT_FOUND)
39014
39104
  throw new NotFoundError(`Class '${appName}/${name}' not found`);
39015
39105
  throw err;
39016
39106
  }
@@ -39109,7 +39199,7 @@ var ClsInstance = class {
39109
39199
  };
39110
39200
 
39111
39201
  // src/queue.ts
39112
- import { ClientError as ClientError5, Status as Status5 } from "nice-grpc";
39202
+ import { ClientError as ClientError6, Status as Status6 } from "nice-grpc";
39113
39203
  var ephemeralObjectHeartbeatSleep = 3e5;
39114
39204
  var queueInitialPutBackoff = 100;
39115
39205
  var queueDefaultPartitionTtl = 24 * 3600 * 1e3;
@@ -39264,7 +39354,7 @@ var Queue = class _Queue {
39264
39354
  });
39265
39355
  break;
39266
39356
  } catch (e) {
39267
- if (e instanceof ClientError5 && e.code === Status5.RESOURCE_EXHAUSTED) {
39357
+ if (e instanceof ClientError6 && e.code === Status6.RESOURCE_EXHAUSTED) {
39268
39358
  delay = Math.min(delay * 2, 3e4);
39269
39359
  if (deadline !== void 0) {
39270
39360
  const remaining = deadline - Date.now();
@@ -39370,5 +39460,6 @@ export {
39370
39460
  QueueEmptyError,
39371
39461
  QueueFullError,
39372
39462
  RemoteError,
39373
- Sandbox2 as Sandbox
39463
+ Sandbox2 as Sandbox,
39464
+ Secret
39374
39465
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modal",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Modal client library for JavaScript",
5
5
  "license": "MIT",
6
6
  "homepage": "https://modal.com/docs",
@@ -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",