@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 +53 -27
- package/dist/checks/provider_checks.js +50 -70
- package/dist/config/provider_config.js +4 -5
- package/dist/errors.d.ts +10 -1
- package/dist/errors.js +29 -7
- package/dist/mappings/mappings.js +8 -10
- package/dist/mappings/provider_mappings.js +28 -13
- package/dist/modal.js +3 -3
- package/package.json +15 -3
- package/dist/mappings.d.ts +0 -17
- package/dist/mappings.js +0 -317
- package/dist/provider.checks.gen.d.ts +0 -3
- package/dist/provider.checks.gen.js +0 -101
- package/dist/provider.config.gen.d.ts +0 -9
- package/dist/provider.config.gen.js +0 -40
- package/dist/provider.errors.gen.d.ts +0 -3
- package/dist/provider.errors.gen.js +0 -36
- package/dist/provider.gen.d.ts +0 -14
- package/dist/provider.gen.js +0 -11
- package/dist/provider.mappings.gen.d.ts +0 -11
- package/dist/provider.mappings.gen.js +0 -161
- package/dist/provider_checks.d.ts +0 -3
- package/dist/provider_checks.js +0 -106
- package/dist/provider_config.d.ts +0 -9
- package/dist/provider_config.js +0 -46
- package/dist/provider_mappings.d.ts +0 -15
- package/dist/provider_mappings.js +0 -179
package/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@sandbox-kit/modal`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
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: {
|
|
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
|
-
|
|
32
|
+
timeout: 120_000,
|
|
22
33
|
});
|
|
23
34
|
|
|
24
35
|
const sandbox = await client.create({
|
|
25
36
|
source: { image: { reference: "alpine:3.21" } },
|
|
26
|
-
|
|
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.
|
|
32
|
-
|
|
43
|
+
Closing the client releases local SDK resources only. Reclaim sandboxes with
|
|
44
|
+
idle/max lifetime policies or `terminate`.
|
|
33
45
|
|
|
34
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
##
|
|
80
|
+
## License
|
|
52
81
|
|
|
53
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
39
|
+
providerError({
|
|
40
40
|
kind: ErrorKind.Unsupported,
|
|
41
|
-
provider: "modal",
|
|
42
41
|
operation: "initialize",
|
|
43
42
|
field,
|
|
44
|
-
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(
|
|
33
|
-
|
|
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,
|
|
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
|
-
|
|
293
|
+
providerError({
|
|
293
294
|
kind: ErrorKind.InvalidArgument,
|
|
294
|
-
provider: "modal",
|
|
295
295
|
operation: "create",
|
|
296
296
|
field,
|
|
297
|
-
message
|
|
297
|
+
message,
|
|
298
298
|
});
|
|
299
299
|
}
|
|
300
300
|
function unsupported(field, message) {
|
|
301
|
-
|
|
301
|
+
providerError({
|
|
302
302
|
kind: ErrorKind.Unsupported,
|
|
303
|
-
provider: "modal",
|
|
304
303
|
operation: "create",
|
|
305
304
|
field,
|
|
306
|
-
message
|
|
305
|
+
message,
|
|
307
306
|
});
|
|
308
307
|
}
|
|
309
308
|
function configInvalid(field, message) {
|
|
310
|
-
|
|
309
|
+
providerError({
|
|
311
310
|
kind: ErrorKind.InvalidArgument,
|
|
312
|
-
provider: "modal",
|
|
313
311
|
operation: "initialize",
|
|
314
312
|
field,
|
|
315
|
-
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
172
|
-
|
|
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 "
|
|
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.
|
|
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.
|
|
69
|
+
"@sandbox-kit/sandbox": "0.1.2",
|
|
58
70
|
"modal": "0.11.1"
|
|
59
71
|
},
|
|
60
72
|
"devDependencies": {
|
package/dist/mappings.d.ts
DELETED
|
@@ -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
|