modal 0.3.9 → 0.3.11

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 CHANGED
@@ -47,7 +47,8 @@ __export(index_exports, {
47
47
  RemoteError: () => RemoteError,
48
48
  Sandbox: () => Sandbox2,
49
49
  SandboxFile: () => SandboxFile,
50
- Secret: () => Secret
50
+ Secret: () => Secret,
51
+ initializeClient: () => initializeClient
51
52
  });
52
53
  module.exports = __toCommonJS(index_exports);
53
54
 
@@ -37858,12 +37859,11 @@ function readConfigFile() {
37858
37859
  if (err.code === "ENOENT") {
37859
37860
  return {};
37860
37861
  }
37861
- throw new Error(`Failed to read or parse .modal.toml: ${err.message}`);
37862
+ return {};
37862
37863
  }
37863
37864
  }
37864
37865
  var config = readConfigFile();
37865
37866
  function getProfile(profileName) {
37866
- profileName = profileName || process.env["MODAL_PROFILE"] || void 0;
37867
37867
  if (!profileName) {
37868
37868
  for (const [name, profileData2] of Object.entries(config)) {
37869
37869
  if (profileData2.active) {
@@ -37872,45 +37872,41 @@ function getProfile(profileName) {
37872
37872
  }
37873
37873
  }
37874
37874
  }
37875
- if (profileName && !Object.hasOwn(config, profileName)) {
37876
- throw new Error(
37877
- `Profile "${profileName}" not found in .modal.toml. Please set the MODAL_PROFILE environment variable or specify a valid profile.`
37878
- );
37879
- }
37880
- const profileData = profileName ? config[profileName] : {};
37881
- const profile2 = {
37875
+ const profileData = profileName && Object.hasOwn(config, profileName) ? config[profileName] : {};
37876
+ const profile = {
37882
37877
  serverUrl: process.env["MODAL_SERVER_URL"] || profileData.server_url || "https://api.modal.com:443",
37883
37878
  tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
37884
37879
  tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
37885
37880
  environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
37886
37881
  imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion
37887
37882
  };
37888
- if (!profile2.tokenId || !profile2.tokenSecret) {
37889
- throw new Error(
37890
- `Profile "${profileName}" is missing token_id or token_secret. Please set them in .modal.toml or as environment variables.`
37891
- );
37892
- }
37893
- return profile2;
37883
+ return profile;
37894
37884
  }
37895
- var profile = getProfile(process.env["MODAL_PROFILE"] || void 0);
37896
37885
  function environmentName(environment) {
37897
- return environment || profile.environment || "";
37886
+ return environment || clientProfile.environment || "";
37898
37887
  }
37899
37888
  function imageBuilderVersion(version) {
37900
- return version || profile.imageBuilderVersion || "2024.10";
37889
+ return version || clientProfile.imageBuilderVersion || "2024.10";
37901
37890
  }
37902
37891
 
37903
37892
  // src/client.ts
37904
- function authMiddleware(profile2) {
37893
+ var defaultProfile = getProfile(process.env["MODAL_PROFILE"]);
37894
+ function authMiddleware(profile) {
37905
37895
  return async function* authMiddleware2(call, options) {
37896
+ if (!profile.tokenId || !profile.tokenSecret) {
37897
+ throw new Error(
37898
+ `Profile is missing token_id or token_secret. Please set them in .modal.toml, or as environment variables, or initializeClient().`
37899
+ );
37900
+ }
37901
+ const { tokenId, tokenSecret } = profile;
37906
37902
  options.metadata ??= new import_nice_grpc.Metadata();
37907
37903
  options.metadata.set(
37908
37904
  "x-modal-client-type",
37909
37905
  String(7 /* CLIENT_TYPE_LIBMODAL */)
37910
37906
  );
37911
37907
  options.metadata.set("x-modal-client-version", "1.0.0");
37912
- options.metadata.set("x-modal-token-id", profile2.tokenId);
37913
- options.metadata.set("x-modal-token-secret", profile2.tokenSecret);
37908
+ options.metadata.set("x-modal-token-id", tokenId);
37909
+ options.metadata.set("x-modal-token-secret", tokenSecret);
37914
37910
  return yield* call.next(call.request, options);
37915
37911
  };
37916
37912
  }
@@ -38016,12 +38012,26 @@ var retryMiddleware = async function* retryMiddleware2(call, options) {
38016
38012
  }
38017
38013
  }
38018
38014
  };
38019
- var channel = (0, import_nice_grpc.createChannel)(profile.serverUrl, void 0, {
38020
- "grpc.max_receive_message_length": 100 * 1024 * 1024,
38021
- "grpc.max_send_message_length": 100 * 1024 * 1024,
38022
- "grpc-node.flow_control_window": 64 * 1024 * 1024
38023
- });
38024
- var client = (0, import_nice_grpc.createClientFactory)().use(authMiddleware(profile)).use(retryMiddleware).use(timeoutMiddleware).create(ModalClientDefinition, channel);
38015
+ function createClient(profile) {
38016
+ const channel = (0, import_nice_grpc.createChannel)(profile.serverUrl, void 0, {
38017
+ "grpc.max_receive_message_length": 100 * 1024 * 1024,
38018
+ "grpc.max_send_message_length": 100 * 1024 * 1024,
38019
+ "grpc-node.flow_control_window": 64 * 1024 * 1024
38020
+ });
38021
+ return (0, import_nice_grpc.createClientFactory)().use(authMiddleware(profile)).use(retryMiddleware).use(timeoutMiddleware).create(ModalClientDefinition, channel);
38022
+ }
38023
+ var clientProfile = defaultProfile;
38024
+ var client = createClient(clientProfile);
38025
+ function initializeClient(options) {
38026
+ const mergedProfile = {
38027
+ ...defaultProfile,
38028
+ tokenId: options.tokenId,
38029
+ tokenSecret: options.tokenSecret,
38030
+ environment: options.environment || defaultProfile.environment
38031
+ };
38032
+ clientProfile = mergedProfile;
38033
+ client = createClient(mergedProfile);
38034
+ }
38025
38035
 
38026
38036
  // src/image.ts
38027
38037
  var Image2 = class {
@@ -38391,7 +38401,9 @@ var Sandbox2 = class {
38391
38401
  const taskId = await this.#getTaskId();
38392
38402
  const resp = await client.containerExec({
38393
38403
  taskId,
38394
- command
38404
+ command,
38405
+ workdir: options?.workdir,
38406
+ timeoutSecs: options?.timeout ? options.timeout / 1e3 : 0
38395
38407
  });
38396
38408
  return new ContainerProcess(resp.execId, options);
38397
38409
  }
@@ -39700,5 +39712,6 @@ var Queue = class _Queue {
39700
39712
  RemoteError,
39701
39713
  Sandbox,
39702
39714
  SandboxFile,
39703
- Secret
39715
+ Secret,
39716
+ initializeClient
39704
39717
  });
package/dist/index.d.cts CHANGED
@@ -139,9 +139,16 @@ type StdioBehavior = "pipe" | "ignore";
139
139
  type StreamMode = "text" | "binary";
140
140
  /** Options to configure a `Sandbox.exec()` operation. */
141
141
  type ExecOptions = {
142
+ /** Specifies text or binary encoding for input and output streams. */
142
143
  mode?: StreamMode;
144
+ /** Whether to pipe or ignore standard output. */
143
145
  stdout?: StdioBehavior;
146
+ /** Whether to pipe or ignore standard error. */
144
147
  stderr?: StdioBehavior;
148
+ /** Working directory to run the command in. */
149
+ workdir?: string;
150
+ /** Timeout for the process in milliseconds. Defaults to 0 (no timeout). */
151
+ timeout?: number;
145
152
  };
146
153
  /** Sandboxes are secure, isolated containers in Modal that boot in seconds. */
147
154
  declare class Sandbox {
@@ -232,6 +239,20 @@ declare class App {
232
239
  imageFromAwsEcr(tag: string, secret: Secret): Promise<Image>;
233
240
  }
234
241
 
242
+ /** Options for initializing a client at runtime. */
243
+ type ClientOptions = {
244
+ tokenId: string;
245
+ tokenSecret: string;
246
+ environment?: string;
247
+ };
248
+ /**
249
+ * Initialize the Modal client, passing in token authentication credentials.
250
+ *
251
+ * You should call this function at the start of your application if not
252
+ * configuring Modal with a `.modal.toml` file or environment variables.
253
+ */
254
+ declare function initializeClient(options: ClientOptions): void;
255
+
235
256
  /** Options for `FunctionCall.get()`. */
236
257
  type FunctionCallGetOptions = {
237
258
  timeout?: number;
@@ -414,4 +435,4 @@ declare class Queue {
414
435
  iterate(options?: QueueIterateOptions): AsyncGenerator<any, void, unknown>;
415
436
  }
416
437
 
417
- 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, SandboxFile, type SandboxFileMode, Secret, type SecretFromNameOptions, type StdioBehavior, type StreamMode };
438
+ export { App, type ClientOptions, 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, SandboxFile, type SandboxFileMode, Secret, type SecretFromNameOptions, type StdioBehavior, type StreamMode, initializeClient };
package/dist/index.d.ts CHANGED
@@ -139,9 +139,16 @@ type StdioBehavior = "pipe" | "ignore";
139
139
  type StreamMode = "text" | "binary";
140
140
  /** Options to configure a `Sandbox.exec()` operation. */
141
141
  type ExecOptions = {
142
+ /** Specifies text or binary encoding for input and output streams. */
142
143
  mode?: StreamMode;
144
+ /** Whether to pipe or ignore standard output. */
143
145
  stdout?: StdioBehavior;
146
+ /** Whether to pipe or ignore standard error. */
144
147
  stderr?: StdioBehavior;
148
+ /** Working directory to run the command in. */
149
+ workdir?: string;
150
+ /** Timeout for the process in milliseconds. Defaults to 0 (no timeout). */
151
+ timeout?: number;
145
152
  };
146
153
  /** Sandboxes are secure, isolated containers in Modal that boot in seconds. */
147
154
  declare class Sandbox {
@@ -232,6 +239,20 @@ declare class App {
232
239
  imageFromAwsEcr(tag: string, secret: Secret): Promise<Image>;
233
240
  }
234
241
 
242
+ /** Options for initializing a client at runtime. */
243
+ type ClientOptions = {
244
+ tokenId: string;
245
+ tokenSecret: string;
246
+ environment?: string;
247
+ };
248
+ /**
249
+ * Initialize the Modal client, passing in token authentication credentials.
250
+ *
251
+ * You should call this function at the start of your application if not
252
+ * configuring Modal with a `.modal.toml` file or environment variables.
253
+ */
254
+ declare function initializeClient(options: ClientOptions): void;
255
+
235
256
  /** Options for `FunctionCall.get()`. */
236
257
  type FunctionCallGetOptions = {
237
258
  timeout?: number;
@@ -414,4 +435,4 @@ declare class Queue {
414
435
  iterate(options?: QueueIterateOptions): AsyncGenerator<any, void, unknown>;
415
436
  }
416
437
 
417
- 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, SandboxFile, type SandboxFileMode, Secret, type SecretFromNameOptions, type StdioBehavior, type StreamMode };
438
+ export { App, type ClientOptions, 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, SandboxFile, type SandboxFileMode, Secret, type SecretFromNameOptions, type StdioBehavior, type StreamMode, initializeClient };
package/dist/index.js CHANGED
@@ -37811,12 +37811,11 @@ function readConfigFile() {
37811
37811
  if (err.code === "ENOENT") {
37812
37812
  return {};
37813
37813
  }
37814
- throw new Error(`Failed to read or parse .modal.toml: ${err.message}`);
37814
+ return {};
37815
37815
  }
37816
37816
  }
37817
37817
  var config = readConfigFile();
37818
37818
  function getProfile(profileName) {
37819
- profileName = profileName || process.env["MODAL_PROFILE"] || void 0;
37820
37819
  if (!profileName) {
37821
37820
  for (const [name, profileData2] of Object.entries(config)) {
37822
37821
  if (profileData2.active) {
@@ -37825,45 +37824,41 @@ function getProfile(profileName) {
37825
37824
  }
37826
37825
  }
37827
37826
  }
37828
- if (profileName && !Object.hasOwn(config, profileName)) {
37829
- throw new Error(
37830
- `Profile "${profileName}" not found in .modal.toml. Please set the MODAL_PROFILE environment variable or specify a valid profile.`
37831
- );
37832
- }
37833
- const profileData = profileName ? config[profileName] : {};
37834
- const profile2 = {
37827
+ const profileData = profileName && Object.hasOwn(config, profileName) ? config[profileName] : {};
37828
+ const profile = {
37835
37829
  serverUrl: process.env["MODAL_SERVER_URL"] || profileData.server_url || "https://api.modal.com:443",
37836
37830
  tokenId: process.env["MODAL_TOKEN_ID"] || profileData.token_id,
37837
37831
  tokenSecret: process.env["MODAL_TOKEN_SECRET"] || profileData.token_secret,
37838
37832
  environment: process.env["MODAL_ENVIRONMENT"] || profileData.environment,
37839
37833
  imageBuilderVersion: process.env["MODAL_IMAGE_BUILDER_VERSION"] || profileData.imageBuilderVersion
37840
37834
  };
37841
- if (!profile2.tokenId || !profile2.tokenSecret) {
37842
- throw new Error(
37843
- `Profile "${profileName}" is missing token_id or token_secret. Please set them in .modal.toml or as environment variables.`
37844
- );
37845
- }
37846
- return profile2;
37835
+ return profile;
37847
37836
  }
37848
- var profile = getProfile(process.env["MODAL_PROFILE"] || void 0);
37849
37837
  function environmentName(environment) {
37850
- return environment || profile.environment || "";
37838
+ return environment || clientProfile.environment || "";
37851
37839
  }
37852
37840
  function imageBuilderVersion(version) {
37853
- return version || profile.imageBuilderVersion || "2024.10";
37841
+ return version || clientProfile.imageBuilderVersion || "2024.10";
37854
37842
  }
37855
37843
 
37856
37844
  // src/client.ts
37857
- function authMiddleware(profile2) {
37845
+ var defaultProfile = getProfile(process.env["MODAL_PROFILE"]);
37846
+ function authMiddleware(profile) {
37858
37847
  return async function* authMiddleware2(call, options) {
37848
+ if (!profile.tokenId || !profile.tokenSecret) {
37849
+ throw new Error(
37850
+ `Profile is missing token_id or token_secret. Please set them in .modal.toml, or as environment variables, or initializeClient().`
37851
+ );
37852
+ }
37853
+ const { tokenId, tokenSecret } = profile;
37859
37854
  options.metadata ??= new Metadata();
37860
37855
  options.metadata.set(
37861
37856
  "x-modal-client-type",
37862
37857
  String(7 /* CLIENT_TYPE_LIBMODAL */)
37863
37858
  );
37864
37859
  options.metadata.set("x-modal-client-version", "1.0.0");
37865
- options.metadata.set("x-modal-token-id", profile2.tokenId);
37866
- options.metadata.set("x-modal-token-secret", profile2.tokenSecret);
37860
+ options.metadata.set("x-modal-token-id", tokenId);
37861
+ options.metadata.set("x-modal-token-secret", tokenSecret);
37867
37862
  return yield* call.next(call.request, options);
37868
37863
  };
37869
37864
  }
@@ -37969,12 +37964,26 @@ var retryMiddleware = async function* retryMiddleware2(call, options) {
37969
37964
  }
37970
37965
  }
37971
37966
  };
37972
- var channel = createChannel(profile.serverUrl, void 0, {
37973
- "grpc.max_receive_message_length": 100 * 1024 * 1024,
37974
- "grpc.max_send_message_length": 100 * 1024 * 1024,
37975
- "grpc-node.flow_control_window": 64 * 1024 * 1024
37976
- });
37977
- var client = createClientFactory().use(authMiddleware(profile)).use(retryMiddleware).use(timeoutMiddleware).create(ModalClientDefinition, channel);
37967
+ function createClient(profile) {
37968
+ const channel = createChannel(profile.serverUrl, void 0, {
37969
+ "grpc.max_receive_message_length": 100 * 1024 * 1024,
37970
+ "grpc.max_send_message_length": 100 * 1024 * 1024,
37971
+ "grpc-node.flow_control_window": 64 * 1024 * 1024
37972
+ });
37973
+ return createClientFactory().use(authMiddleware(profile)).use(retryMiddleware).use(timeoutMiddleware).create(ModalClientDefinition, channel);
37974
+ }
37975
+ var clientProfile = defaultProfile;
37976
+ var client = createClient(clientProfile);
37977
+ function initializeClient(options) {
37978
+ const mergedProfile = {
37979
+ ...defaultProfile,
37980
+ tokenId: options.tokenId,
37981
+ tokenSecret: options.tokenSecret,
37982
+ environment: options.environment || defaultProfile.environment
37983
+ };
37984
+ clientProfile = mergedProfile;
37985
+ client = createClient(mergedProfile);
37986
+ }
37978
37987
 
37979
37988
  // src/image.ts
37980
37989
  var Image2 = class {
@@ -38344,7 +38353,9 @@ var Sandbox2 = class {
38344
38353
  const taskId = await this.#getTaskId();
38345
38354
  const resp = await client.containerExec({
38346
38355
  taskId,
38347
- command
38356
+ command,
38357
+ workdir: options?.workdir,
38358
+ timeoutSecs: options?.timeout ? options.timeout / 1e3 : 0
38348
38359
  });
38349
38360
  return new ContainerProcess(resp.execId, options);
38350
38361
  }
@@ -39652,5 +39663,6 @@ export {
39652
39663
  RemoteError,
39653
39664
  Sandbox2 as Sandbox,
39654
39665
  SandboxFile,
39655
- Secret
39666
+ Secret,
39667
+ initializeClient
39656
39668
  };
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "modal",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "Modal client library for JavaScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://modal.com/docs",
7
- "repository": "github:modal-labs/libmodal",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/modal-labs/libmodal.git"
10
+ },
8
11
  "bugs": "https://github.com/modal-labs/libmodal/issues",
9
12
  "type": "module",
10
13
  "sideEffects": false,
@@ -30,9 +33,9 @@
30
33
  "lint": "eslint",
31
34
  "prepare": "scripts/gen-proto.sh",
32
35
  "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"
36
+ "version": "npm run check && git add -A && git commit -m \"modal-js/v$npm_package_version\"",
37
+ "prepublishOnly": "npm run build && git push",
38
+ "postpublish": "git tag modal-js/v$npm_package_version && git push --tags"
36
39
  },
37
40
  "dependencies": {
38
41
  "long": "^5.3.1",