@sandbox-kit/modal 0.1.0 → 0.1.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,13 +1,17 @@
1
- # Modal provider for Sandbox Kit
1
+ # `@sandbox-kit/modal`
2
2
 
3
- Independent package over `modal@0.11.1`, published separately from the core
4
- `@sandbox-kit/sandbox` client. Use it through that shared API.
3
+ Modal provider for [`@sandbox-kit/sandbox`](https://www.npmjs.com/package/@sandbox-kit/sandbox).
4
+ Use the shared client API; this package supplies the `modal()` provider.
5
+
6
+ ## Install
5
7
 
6
8
  ```sh
7
9
  npm install @sandbox-kit/sandbox @sandbox-kit/modal
8
10
  ```
9
11
 
10
- ## Usage
12
+ Requires Node.js 20, 22, or 24.15+, and a Modal token pair.
13
+
14
+ ## Quick start
11
15
 
12
16
  ```ts
13
17
  import { modal } from "@sandbox-kit/modal";
@@ -16,41 +20,63 @@ import { Client } from "@sandbox-kit/sandbox";
16
20
  await using client = new Client({
17
21
  provider: modal(),
18
22
  auth: {
19
- tokenPair: { id: "...", secret: "..." },
23
+ tokenPair: {
24
+ id: process.env.MODAL_TOKEN_ID!,
25
+ secret: process.env.MODAL_TOKEN_SECRET!,
26
+ },
27
+ },
28
+ scope: {
29
+ appName: process.env.MODAL_APP_NAME!,
30
+ environment: process.env.MODAL_ENVIRONMENT ?? "main",
20
31
  },
21
- scope: { appName: "my-app", environment: "main" },
32
+ timeout: 120_000,
22
33
  });
23
34
 
24
35
  const sandbox = await client.create({
25
36
  source: { image: { reference: "alpine:3.21" } },
26
- provisioning: { timeout: 120_000 },
37
+ resources: { cpuCores: 0.5, memoryMib: 512n },
38
+ lifetime: { maximumLifetime: 5 * 60_000 },
27
39
  });
28
40
  console.log(sandbox.id);
29
41
  ```
30
42
 
31
- Closing the client releases local SDK resources only. The Modal app must already
32
- exist.
43
+ Closing the client releases local SDK resources only. Reclaim sandboxes with
44
+ idle/max lifetime policies or `terminate`.
33
45
 
34
- ## Examples
46
+ ## Configuration
47
+
48
+ | Setting | Notes |
49
+ | -------------- | ---------------------------------------------------------- |
50
+ | Token pair | `auth: { tokenPair: { id, secret } }` |
51
+ | OAuth refresh | Supported with client ID and exactly one secret or JWT key |
52
+ | Omitted `auth` | Modal SDK environment / profile credentials |
53
+ | App | `scope.appName` — required |
54
+ | Environment | `scope.environment` (default often `main`) |
55
+ | Region | `region` — default placement preference |
56
+ | Endpoint | Not supported |
35
57
 
36
- | Example | Project |
37
- | ---------- | ---------------------------------------------------------------------------------------------------------- |
38
- | Creation | [create-modal-sandbox](../../../../examples/typescript/modal/create-modal-sandbox/README.md) |
39
- | Resources | [create-modal-with-resources](../../../../examples/typescript/modal/create-modal-with-resources/README.md) |
40
- | Attach | [attach-modal-sandbox](../../../../examples/typescript/modal/attach-modal-sandbox/README.md) |
41
- | Full index | [TypeScript examples](../../../../examples/typescript/README.md) |
58
+ ## What you can do
42
59
 
43
- ## Capabilities
60
+ **Create** from a registry image with runtime (command, workdir, PTY), gVisor or
61
+ Linux VM isolation, CPU/memory, placement, network policy and ports, secrets,
62
+ OIDC workload identity, readiness probes, timeouts, labels, and verbose mode.
63
+
64
+ **Lifecycle** on the handle: `attach`, `terminate`, and local `close`.
65
+ Provider-verified `get` / `refresh`, start, stop, pause, archive, and delete are
66
+ unsupported.
67
+
68
+ When you set resources, Modal requires at least 0.125 CPU cores and 128 MiB
69
+ memory. Omitted values keep Modal defaults. Disk size cannot be raised at create.
70
+
71
+ ## Examples
44
72
 
45
- Modal supports image creation, attach, terminate, and local handle detachment.
46
- The creation adapter covers runtime command/workdir/PTY, gVisor or VM isolation,
47
- CPU and memory reservations and limits, placement, network policy and ports,
48
- secrets, OIDC workload identity, readiness, timeouts, labels, and verbose mode.
49
- Unsupported shared intent is rejected before contacting Modal.
73
+ | Example | Project |
74
+ | ---------- | --------------------------------------------------------------------------------------------------------------------------------- |
75
+ | Creation | [create-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/create-modal-sandbox) |
76
+ | Resources | [create-modal-with-resources](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/create-modal-with-resources) |
77
+ | Attach | [attach-modal-sandbox](https://github.com/sandbox-kit/kit/tree/main/examples/typescript/modal/attach-modal-sandbox) |
78
+ | Full index | [TypeScript examples](https://github.com/sandbox-kit/kit/tree/main/examples/typescript) |
50
79
 
51
- ## Implementation notes
80
+ ## License
52
81
 
53
- Checks and portable field mappings are handwritten in `checks/provider_checks.ts`,
54
- `mappings/provider_mappings.ts`, and `config/provider_config.ts`, kept in sync with
55
- `specs/providers/modal.yaml`. `src/modal.ts` owns SDK call ordering;
56
- `src/mappings.ts` owns remaining composition those helpers do not cover.
82
+ MIT
@@ -1,18 +1,34 @@
1
- import { ErrorKind, sandboxError, CreateFieldEnvironment, CreateFieldNetworkInboundCidrsEntries, CreateFieldNetworkOutboundCidrsEntries, CreateFieldNetworkOutboundDomainsEntries, CreateFieldPlacementCloud, CreateFieldResourcesCpuCores, CreateFieldResourcesMemoryMib, CreateFieldRuntimeWorkingDirectory } from "@sandbox-kit/sandbox";
1
+ import { ErrorKind, CreateFieldEnvironment, CreateFieldNetworkInboundCidrsEntries, CreateFieldNetworkOutboundCidrsEntries, CreateFieldNetworkOutboundDomainsEntries, CreateFieldPlacementCloud, CreateFieldResourcesCpuCores, CreateFieldResourcesMemoryMib, CreateFieldRuntimeWorkingDirectory, validCidr, validDomain, validEnvName, } from "@sandbox-kit/sandbox";
2
+ import { providerError } from "#errors.js";
2
3
  // validateProviderCreate rejects creation settings this provider cannot honor.
3
4
  // Rules are inventoried in specs/providers/modal.yaml checks.
4
5
  export function validateProviderCreate(request) {
5
6
  const cpuCores = request.resources?.cpuCores;
6
7
  if (cpuCores !== undefined && cpuCores < 0.125) {
7
- fail(ErrorKind.InvalidArgument, CreateFieldResourcesCpuCores, "resources.cpu_cores is outside supported values");
8
+ providerError({
9
+ kind: ErrorKind.InvalidArgument,
10
+ operation: "create",
11
+ field: CreateFieldResourcesCpuCores,
12
+ message: "resources.cpu_cores is outside supported values",
13
+ });
8
14
  }
9
15
  const memoryMib = request.resources?.memoryMib;
10
16
  if (memoryMib !== undefined && memoryMib < BigInt("128")) {
11
- fail(ErrorKind.InvalidArgument, CreateFieldResourcesMemoryMib, "resources.memory_mib is outside supported values");
17
+ providerError({
18
+ kind: ErrorKind.InvalidArgument,
19
+ operation: "create",
20
+ field: CreateFieldResourcesMemoryMib,
21
+ message: "resources.memory_mib is outside supported values",
22
+ });
12
23
  }
13
24
  const workingDirectory = request.runtime?.workingDirectory;
14
25
  if (workingDirectory !== undefined && !workingDirectory.startsWith("/")) {
15
- fail(ErrorKind.InvalidArgument, CreateFieldRuntimeWorkingDirectory, "runtime.working_directory is outside supported values");
26
+ providerError({
27
+ kind: ErrorKind.InvalidArgument,
28
+ operation: "create",
29
+ field: CreateFieldRuntimeWorkingDirectory,
30
+ message: "runtime.working_directory is outside supported values",
31
+ });
16
32
  }
17
33
  const cloud = request.placement?.cloud;
18
34
  if (cloud !== undefined &&
@@ -20,87 +36,51 @@ export function validateProviderCreate(request) {
20
36
  cloud !== "gcp" &&
21
37
  cloud !== "oci" &&
22
38
  cloud !== "auto") {
23
- fail(ErrorKind.Unsupported, CreateFieldPlacementCloud, "placement.cloud is outside supported values");
39
+ providerError({
40
+ kind: ErrorKind.Unsupported,
41
+ operation: "create",
42
+ field: CreateFieldPlacementCloud,
43
+ message: "placement.cloud is outside supported values",
44
+ });
24
45
  }
25
46
  for (const value of request.network?.outboundCidrs ?? []) {
26
47
  if (value !== "" && !validCidr(value)) {
27
- fail(ErrorKind.InvalidArgument, CreateFieldNetworkOutboundCidrsEntries, "network.outbound_cidrs.entries is outside supported values");
48
+ providerError({
49
+ kind: ErrorKind.InvalidArgument,
50
+ operation: "create",
51
+ field: CreateFieldNetworkOutboundCidrsEntries,
52
+ message: "network.outbound_cidrs.entries is outside supported values",
53
+ });
28
54
  }
29
55
  }
30
56
  for (const value of request.network?.inboundCidrs ?? []) {
31
57
  if (!validCidr(value)) {
32
- fail(ErrorKind.InvalidArgument, CreateFieldNetworkInboundCidrsEntries, "network.inbound_cidrs.entries is outside supported values");
58
+ providerError({
59
+ kind: ErrorKind.InvalidArgument,
60
+ operation: "create",
61
+ field: CreateFieldNetworkInboundCidrsEntries,
62
+ message: "network.inbound_cidrs.entries is outside supported values",
63
+ });
33
64
  }
34
65
  }
35
66
  for (const value of request.network?.outboundDomains ?? []) {
36
67
  if (value !== "" && !validDomain(value)) {
37
- fail(ErrorKind.InvalidArgument, CreateFieldNetworkOutboundDomainsEntries, "network.outbound_domains.entries is outside supported values");
68
+ providerError({
69
+ kind: ErrorKind.InvalidArgument,
70
+ operation: "create",
71
+ field: CreateFieldNetworkOutboundDomainsEntries,
72
+ message: "network.outbound_domains.entries is outside supported values",
73
+ });
38
74
  }
39
75
  }
40
76
  for (const value of Object.keys(request.environment ?? {})) {
41
77
  if (!validEnvName(value)) {
42
- fail(ErrorKind.InvalidArgument, CreateFieldEnvironment, "environment is outside supported values");
78
+ providerError({
79
+ kind: ErrorKind.InvalidArgument,
80
+ operation: "create",
81
+ field: CreateFieldEnvironment,
82
+ message: "environment is outside supported values",
83
+ });
43
84
  }
44
85
  }
45
86
  }
46
- function validEnvName(value) {
47
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
48
- }
49
- function validDomain(value) {
50
- const domain = value.startsWith("*.") ? value.slice(2) : value;
51
- return (domain.length <= 253 &&
52
- /^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.?$/i.test(domain));
53
- }
54
- function validCidr(value) {
55
- const separator = value.lastIndexOf("/");
56
- if (separator <= 0)
57
- return false;
58
- const address = value.slice(0, separator);
59
- const prefix = Number(value.slice(separator + 1));
60
- if (!Number.isInteger(prefix))
61
- return false;
62
- return address.includes(":")
63
- ? prefix >= 0 && prefix <= 128 && validIpv6(address)
64
- : prefix >= 0 && prefix <= 32 && validIpv4(address);
65
- }
66
- function validIpv4(value) {
67
- const parts = value.split(".");
68
- return (parts.length === 4 &&
69
- parts.every((part) => /^(0|[1-9][0-9]{0,2})$/.test(part) && Number(part) <= 255));
70
- }
71
- function validIpv6(value) {
72
- if ((value.match(/::/g)?.length ?? 0) > 1)
73
- return false;
74
- const halves = value.split("::");
75
- if (halves.length > 2)
76
- return false;
77
- const count = (part) => {
78
- if (part === "")
79
- return 0;
80
- const groups = part.split(":");
81
- let total = 0;
82
- for (const group of groups) {
83
- if (/^[0-9a-f]{1,4}$/i.test(group))
84
- total++;
85
- else if (validIpv4(group))
86
- total += 2;
87
- else
88
- return undefined;
89
- }
90
- return total;
91
- };
92
- const left = count(halves[0] ?? "");
93
- const right = count(halves[1] ?? "");
94
- return (left !== undefined &&
95
- right !== undefined &&
96
- (halves.length === 2 ? left + right < 8 : left === 8));
97
- }
98
- function fail(kind, field, message) {
99
- throw sandboxError({
100
- kind,
101
- provider: "modal",
102
- operation: "create",
103
- field,
104
- message: "sandbox-kit modal: " + message,
105
- });
106
- }
@@ -1,10 +1,10 @@
1
1
  // Client configuration composition for the native SDK constructor.
2
2
  // Kept in sync with specs/providers/modal.yaml client: rules (not emitted).
3
- import { ErrorKind, sandboxError, validateConfig, ConfigFieldAuth, ConfigFieldEndpoint, ConfigFieldScopeProjectId } from "@sandbox-kit/sandbox";
3
+ import { ErrorKind, ConfigFieldAuth, ConfigFieldEndpoint, ConfigFieldScopeProjectId, } from "@sandbox-kit/sandbox";
4
4
  import { mapClientScope, mapOAuthAuth, mapTokenPairCredentials, } from "#mappings/provider_mappings.js";
5
+ import { providerError } from "#errors.js";
5
6
  export function mapGeneratedClientConfig(config) {
6
7
  const source = config;
7
- validateConfig(source, "modal", "initialize");
8
8
  const target = {};
9
9
  if (source.endpoint !== undefined)
10
10
  unsupported(ConfigFieldEndpoint, "Endpoint cannot be configured through this SDK's public client constructor");
@@ -36,11 +36,10 @@ export function captureProviderState(config) {
36
36
  };
37
37
  }
38
38
  function unsupported(field, message) {
39
- throw sandboxError({
39
+ providerError({
40
40
  kind: ErrorKind.Unsupported,
41
- provider: "modal",
42
41
  operation: "initialize",
43
42
  field,
44
- message: "sandbox-kit modal: " + message,
43
+ message,
45
44
  });
46
45
  }
package/dist/errors.d.ts CHANGED
@@ -1,2 +1,11 @@
1
- import { SandboxError } from "@sandbox-kit/sandbox";
1
+ import { SandboxError, type ErrorInfo } from "@sandbox-kit/sandbox";
2
+ /** Inputs for throwing a Modal-scoped validation or mapping error. */
3
+ export interface ProviderErrorInput {
4
+ kind: ErrorInfo["kind"];
5
+ operation: string;
6
+ field: string;
7
+ message: string;
8
+ }
2
9
  export declare function mapModalError(error: unknown, operation: string): SandboxError;
10
+ /** Local throw helper for mappings, checks, and config. */
11
+ export declare function providerError(input: ProviderErrorInput): never;
package/dist/errors.js CHANGED
@@ -1,15 +1,15 @@
1
1
  // Native Modal error translation is handwritten.
2
2
  // Classification order: existing SandboxError, abort/timeout DOMException,
3
3
  // then native Modal types, then unknown. Cause stays on SandboxError.cause.
4
- import { AlreadyExistsError, ClientClosedError, ConflictError, InvalidError, NotFoundError, ResourceExhaustedError, SandboxTimeoutError, TimeoutError } from "modal";
5
- import { ErrorKind, SandboxError, sandboxError } from "@sandbox-kit/sandbox";
4
+ import { AlreadyExistsError, ClientClosedError, ConflictError, InvalidError, NotFoundError, ResourceExhaustedError, SandboxTimeoutError, TimeoutError, } from "modal";
5
+ import { ErrorKind, SandboxError, sandboxError, } from "@sandbox-kit/sandbox";
6
6
  export function mapModalError(error, operation) {
7
7
  if (error instanceof SandboxError)
8
8
  return error;
9
9
  if (error instanceof DOMException && error.name === "AbortError")
10
- return create(ErrorKind.Canceled, error, operation);
10
+ return create({ kind: ErrorKind.Canceled, error, operation });
11
11
  if (error instanceof DOMException && error.name === "TimeoutError")
12
- return create(ErrorKind.Timeout, error, operation);
12
+ return create({ kind: ErrorKind.Timeout, error, operation });
13
13
  let kind = ErrorKind.Unknown;
14
14
  if (kind === ErrorKind.Unknown && error instanceof InvalidError)
15
15
  kind = ErrorKind.InvalidArgument;
@@ -27,8 +27,30 @@ export function mapModalError(error, operation) {
27
27
  kind = ErrorKind.Timeout;
28
28
  if (kind === ErrorKind.Unknown && error instanceof ClientClosedError)
29
29
  kind = ErrorKind.FailedPrecondition;
30
- return create(kind, error, operation);
30
+ return create({ kind, error, operation });
31
31
  }
32
- function create(kind, error, operation, statusCode, providerCode, providerSource) {
33
- return sandboxError({ kind, provider: "modal", operation, field: "", message: error instanceof Error ? error.message : "sandbox-kit modal: provider operation failed", ...(statusCode === undefined ? {} : { statusCode }), ...(providerCode === undefined ? {} : { providerCode }), ...(providerSource === undefined ? {} : { providerSource }) }, error);
32
+ function create(input) {
33
+ const { kind, error, operation, statusCode, providerCode, providerSource } = input;
34
+ return sandboxError({
35
+ kind,
36
+ provider: "modal",
37
+ operation,
38
+ field: "",
39
+ message: error instanceof Error
40
+ ? error.message
41
+ : "sandbox-kit modal: provider operation failed",
42
+ ...(statusCode === undefined ? {} : { statusCode }),
43
+ ...(providerCode === undefined ? {} : { providerCode }),
44
+ ...(providerSource === undefined ? {} : { providerSource }),
45
+ }, error);
46
+ }
47
+ /** Local throw helper for mappings, checks, and config. */
48
+ export function providerError(input) {
49
+ throw sandboxError({
50
+ kind: input.kind,
51
+ provider: "modal",
52
+ operation: input.operation,
53
+ field: input.field,
54
+ message: "sandbox-kit modal: " + input.message,
55
+ });
34
56
  }
@@ -1,9 +1,10 @@
1
1
  // Provider-specific orchestration around generated portable field mappings.
2
2
  import { Probe, } from "modal";
3
- import { EgressMode, ErrorKind, IsolationKind, PolicyMode, PortTransport, SecretInjection, SandboxState, ValueOrigin, WaitCondition, sandboxError, CreateFieldIsolation, CreateFieldIsolationKind, CreateFieldLifetime, CreateFieldLifetimeIdleTerminateAfter, CreateFieldLifetimeIdleTerminateMode, CreateFieldNetwork, CreateFieldNetworkEgress, CreateFieldNetworkPortsPort, CreateFieldNetworkPortsTransport, CreateFieldPlacementTarget, CreateFieldProvisioningTimeout, CreateFieldProvisioningWaitFor, CreateFieldReadiness, CreateFieldRuntime, CreateFieldSecuritySecretsEnvironmentVariable, CreateFieldSecuritySecretsInjection, CreateFieldSource, ConfigFieldScopeAppName, CreateFieldName, CreateFieldNetworkInboundCidrs, CreateFieldNetworkProxyReference, CreateFieldProvisioningQueueTimeout, CreateFieldResourcesCpuLimitCores, CreateFieldResourcesDiskMib, CreateFieldResourcesMemoryLimitMib, CreateFieldResourcesMemoryMib, CreateFieldSecurityPublicAccess, CreateFieldSecuritySecretsReference, CreateFieldSourceImageReference } from "@sandbox-kit/sandbox";
3
+ import { EgressMode, ErrorKind, IsolationKind, PolicyMode, PortTransport, SecretInjection, SandboxState, ValueOrigin, WaitCondition, CreateFieldIsolation, CreateFieldIsolationKind, CreateFieldLifetime, CreateFieldLifetimeIdleTerminateAfter, CreateFieldLifetimeIdleTerminateMode, CreateFieldNetwork, CreateFieldNetworkEgress, CreateFieldNetworkPortsPort, CreateFieldNetworkPortsTransport, CreateFieldPlacementTarget, CreateFieldProvisioningTimeout, CreateFieldProvisioningWaitFor, CreateFieldReadiness, CreateFieldRuntime, CreateFieldSecuritySecretsEnvironmentVariable, CreateFieldSecuritySecretsInjection, CreateFieldSource, ConfigFieldScopeAppName, CreateFieldName, CreateFieldNetworkInboundCidrs, CreateFieldNetworkProxyReference, CreateFieldProvisioningQueueTimeout, CreateFieldResourcesCpuLimitCores, CreateFieldResourcesDiskMib, CreateFieldResourcesMemoryLimitMib, CreateFieldResourcesMemoryMib, CreateFieldSecurityPublicAccess, CreateFieldSecuritySecretsReference, CreateFieldSourceImageReference, } from "@sandbox-kit/sandbox";
4
4
  import { mapCommonCreateFields as generatedMapCommonCreateFields, mapIdleDuration as generatedMapIdleDuration, mapLifetimeDuration as generatedMapLifetimeDuration, mapResources as generatedMapResources, mapSandboxIdentity as generatedMapSandboxIdentity, } from "./provider_mappings.js";
5
5
  import { validateProviderCreate } from "#checks/provider_checks.js";
6
6
  import { mapGeneratedClientConfig } from "#config/provider_config.js";
7
+ import { providerError } from "#errors.js";
7
8
  export function mapClientConfig(config) {
8
9
  const result = mapGeneratedClientConfig(config);
9
10
  if (config.timeout !== undefined)
@@ -289,29 +290,26 @@ function finiteDurationMs(v, f, zero) {
289
290
  return v;
290
291
  }
291
292
  function invalid(field, message) {
292
- throw sandboxError({
293
+ providerError({
293
294
  kind: ErrorKind.InvalidArgument,
294
- provider: "modal",
295
295
  operation: "create",
296
296
  field,
297
- message: "sandbox-kit modal: " + message,
297
+ message,
298
298
  });
299
299
  }
300
300
  function unsupported(field, message) {
301
- throw sandboxError({
301
+ providerError({
302
302
  kind: ErrorKind.Unsupported,
303
- provider: "modal",
304
303
  operation: "create",
305
304
  field,
306
- message: "sandbox-kit modal: " + message,
305
+ message,
307
306
  });
308
307
  }
309
308
  function configInvalid(field, message) {
310
- throw sandboxError({
309
+ providerError({
311
310
  kind: ErrorKind.InvalidArgument,
312
- provider: "modal",
313
311
  operation: "initialize",
314
312
  field,
315
- message: "sandbox-kit modal: " + message,
313
+ message,
316
314
  });
317
315
  }
@@ -1,6 +1,7 @@
1
1
  // Provider field mappings between shared CreateOptions/Config and the native SDK.
2
2
  // Inventoried in specs/providers/modal.yaml groups; kept in sync by hand (not emitted).
3
- import { ErrorKind, ValueOrigin, sandboxError, CreateFieldResourcesMemoryLimitMib, CreateFieldResourcesMemoryMib, InfoFieldId, CreateFieldLifetimeIdleTerminateAfter, CreateFieldLifetimeMaximumLifetime, CreateFieldResourcesCpuCores, CreateFieldResourcesCpuLimitCores } from "@sandbox-kit/sandbox";
3
+ import { ErrorKind, ValueOrigin, CreateFieldResourcesMemoryLimitMib, CreateFieldResourcesMemoryMib, InfoFieldId, CreateFieldLifetimeIdleTerminateAfter, CreateFieldLifetimeMaximumLifetime, CreateFieldResourcesCpuCores, CreateFieldResourcesCpuLimitCores, } from "@sandbox-kit/sandbox";
4
+ import { providerError } from "#errors.js";
4
5
  export function mapSandboxIdentity(source, operation = "create") {
5
6
  const target = {};
6
7
  if (source === undefined)
@@ -71,7 +72,12 @@ export function mapResources(source, operation = "create") {
71
72
  if (source.memoryMib !== undefined) {
72
73
  const value = source.memoryMib;
73
74
  if (value > 2147483647n)
74
- mappingError(ErrorKind.InvalidArgument, CreateFieldResourcesMemoryMib, "memory_mib cannot be represented", operation);
75
+ mappingError({
76
+ kind: ErrorKind.InvalidArgument,
77
+ field: CreateFieldResourcesMemoryMib,
78
+ message: "memory_mib cannot be represented",
79
+ operation,
80
+ });
75
81
  target.memoryMiB = Number(value);
76
82
  }
77
83
  }
@@ -79,7 +85,12 @@ export function mapResources(source, operation = "create") {
79
85
  if (source.memoryLimitMib !== undefined) {
80
86
  const value = source.memoryLimitMib;
81
87
  if (value > 2147483647n)
82
- mappingError(ErrorKind.InvalidArgument, CreateFieldResourcesMemoryLimitMib, "memory_limit_mib cannot be represented", operation);
88
+ mappingError({
89
+ kind: ErrorKind.InvalidArgument,
90
+ field: CreateFieldResourcesMemoryLimitMib,
91
+ message: "memory_limit_mib cannot be represented",
92
+ operation,
93
+ });
83
94
  target.memoryLimitMiB = Number(value);
84
95
  }
85
96
  }
@@ -114,7 +125,12 @@ function scaledCpuCores(value, field, operation) {
114
125
  value < 0 ||
115
126
  value !== scaled / 1000 ||
116
127
  scaled > 4_294_967_295) {
117
- mappingError(ErrorKind.InvalidArgument, field, field.slice(field.lastIndexOf(".") + 1) + " cannot be represented", operation);
128
+ mappingError({
129
+ kind: ErrorKind.InvalidArgument,
130
+ field,
131
+ message: field.slice(field.lastIndexOf(".") + 1) + " cannot be represented",
132
+ operation,
133
+ });
118
134
  }
119
135
  return value * 1000 < scaled ? scaled / 1000 : value;
120
136
  }
@@ -124,7 +140,12 @@ function durationSecondsMs(value, field, maximumSeconds, operation) {
124
140
  value <= 0 ||
125
141
  value % 1000 !== 0 ||
126
142
  value / 1000 > maximumSeconds) {
127
- mappingError(ErrorKind.InvalidArgument, field, field.slice(field.lastIndexOf(".") + 1) + " cannot be represented", operation);
143
+ mappingError({
144
+ kind: ErrorKind.InvalidArgument,
145
+ field,
146
+ message: field.slice(field.lastIndexOf(".") + 1) + " cannot be represented",
147
+ operation,
148
+ });
128
149
  }
129
150
  return value;
130
151
  }
@@ -168,12 +189,6 @@ export function mapOAuthAuth(source, operation = "create") {
168
189
  }
169
190
  return target;
170
191
  }
171
- function mappingError(kind, field, message, operation) {
172
- throw sandboxError({
173
- kind,
174
- provider: "modal",
175
- operation,
176
- field,
177
- message: "sandbox-kit modal: " + message,
178
- });
192
+ function mappingError(input) {
193
+ providerError(input);
179
194
  }
package/dist/modal.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ModalClient, } from "modal";
2
- import { LifecycleCapability } from "@sandbox-kit/sandbox";
2
+ import { LifecycleCapability, } from "@sandbox-kit/sandbox";
3
3
  import { mapClientConfig, mapCreateRequest, mapSandboxInfo, } from "#mappings/mappings.js";
4
- import { mapModalError } from "./errors.js";
4
+ import { mapModalError } from "#errors.js";
5
5
  import { BackendBase, ProviderBase } from "./provider.js";
6
- import { captureProviderState } from "#config/provider_config.js";
6
+ import { captureProviderState, } from "#config/provider_config.js";
7
7
  /** @internal Exported for adapter boundary tests, but not from the package root. */
8
8
  export class ModalProvider extends ProviderBase {
9
9
  nativeFactory;
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@sandbox-kit/modal",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "modal provider for sandbox kit",
5
+ "keywords": [
6
+ "sandbox-kit",
7
+ "sandbox",
8
+ "modal",
9
+ "sdk",
10
+ "provider"
11
+ ],
5
12
  "license": "MIT",
6
13
  "type": "module",
7
14
  "packageManager": "npm@11.19.0",
@@ -45,16 +52,21 @@
45
52
  "#config/*.js": {
46
53
  "@sandbox-kit/source": "./src/config/*.ts",
47
54
  "default": "./dist/config/*.js"
55
+ },
56
+ "#errors.js": {
57
+ "@sandbox-kit/source": "./src/errors.ts",
58
+ "default": "./dist/errors.js"
48
59
  }
49
60
  },
50
61
  "scripts": {
62
+ "clean": "rm -rf dist",
51
63
  "build": "tsc -p tsconfig.build.json",
52
- "prepublishOnly": "npm run build",
64
+ "prepublishOnly": "npm run clean && npm run build",
53
65
  "test": "tsc -p tsconfig.test.json && vitest run"
54
66
  },
55
67
  "dependencies": {
56
68
  "@bufbuild/protobuf": "2.16.0",
57
- "@sandbox-kit/sandbox": "0.1.0",
69
+ "@sandbox-kit/sandbox": "0.1.2",
58
70
  "modal": "0.11.1"
59
71
  },
60
72
  "devDependencies": {
@@ -1,17 +0,0 @@
1
- import { type ModalClientParams, type Sandbox, type SandboxCreateParams } from "modal";
2
- import { type Config, type CreateOptions, type SandboxInfo } from "@sandbox-kit/sandbox";
3
- import type { ProviderState } from "./provider_config.js";
4
- export interface ModalCreatePlan {
5
- readonly app: string;
6
- readonly environment?: string;
7
- readonly image: string;
8
- readonly params: SandboxCreateParams;
9
- readonly secretNames: readonly string[];
10
- readonly proxyName?: string;
11
- readonly waitUntilReady: boolean;
12
- readonly readyTimeoutMs?: number;
13
- }
14
- export declare function mapClientConfig(config: Config): ModalClientParams;
15
- export declare function mapCreateRequest(request: CreateOptions, config: ProviderState): ModalCreatePlan;
16
- export declare function mapSandboxInfo(value: Sandbox, request?: CreateOptions): SandboxInfo;
17
- //# sourceMappingURL=mappings.d.ts.map