@sandbox-kit/sandbox 0.0.0-stage → 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sandbox-kit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,70 @@
1
- # Temporary Holding Version
1
+ # Sandbox Kit for TypeScript
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Core client package (`@sandbox-kit/sandbox`). Providers such as
4
+ `@sandbox-kit/daytona` and `@sandbox-kit/modal` are published
5
+ separately and plug into this module. Apps and providers share public
6
+ `CreateOptions` / `ClientConfig` (`Config` plus `provider`): nested exclusive
7
+ fields (`auth: { apiKey: … }`, `source: { image: … }`, `readiness: { command: … }`),
8
+ plain maps/allowlists (`outboundCidrs: string[]`), and millisecond timeouts.
9
+ `ErrorInfo.field` uses canonical protobuf paths (`CreateField*` / `ConfigField*` /
10
+ `InfoField*`), matching Go. Closing the client releases local provider SDK
11
+ resources only; it does not stop or delete cloud sandboxes.
12
+
13
+ ## Public input → wire boundary
14
+
15
+ Applications and provider backends speak the **public** shapes above. Inside
16
+ `Client`, requests are converted before Protovalidate and provider mapping:
17
+
18
+ 1. **Public input** — ms numbers, nested oneofs, `string[]` allowlists, plain
19
+ `providerOptions` maps.
20
+ 2. **`materialize*`** — package-private conversion to protobuf wire messages.
21
+ 3. **Validate** — shared Protovalidate rules (`secure_endpoint` stays handwritten),
22
+ then provider checks.
23
+ 4. **Provider mappings** — native SDK calls using the validated wire request.
24
+
25
+ Wire types stay package-private to the client.
26
+
27
+ ## Usage
28
+
29
+ ```ts
30
+ import {
31
+ Client,
32
+ type ClientConfig,
33
+ type CreateOptions,
34
+ } from "@sandbox-kit/sandbox";
35
+ import { daytona } from "@sandbox-kit/daytona";
36
+
37
+ const config: ClientConfig = {
38
+ provider: daytona(),
39
+ auth: { apiKey: { key: process.env.DAYTONA_API_KEY! } },
40
+ timeout: 120_000,
41
+ };
42
+
43
+ const createOptions: CreateOptions = {
44
+ source: { image: { reference: "daytonaio/playground:latest" } },
45
+ provisioning: { timeout: 120_000 },
46
+ };
47
+
48
+ await using client = new Client(config);
49
+ const sandbox = await client.create(createOptions);
50
+ console.log(sandbox.id);
51
+ ```
52
+
53
+ Prefer `await using` when the runtime supports explicit resource management;
54
+ otherwise call `await client.close()` in `finally`. Both forms have identical
55
+ cleanup semantics.
56
+
57
+ ## Examples
58
+
59
+ | Language | Index |
60
+ | ---------- | ------------------------------------------------------------- |
61
+ | TypeScript | [examples/typescript](../../../examples/typescript/README.md) |
62
+ | Go | [examples/go](../../../examples/go/README.md) |
63
+
64
+ ```sh
65
+ npm install @sandbox-kit/sandbox @sandbox-kit/daytona
66
+ # or: npm install @sandbox-kit/sandbox @sandbox-kit/modal
67
+ ```
68
+
69
+ See the [root README](../../../README.md) for a full create snippet and the
70
+ [TypeScript workspace README](../README.md) for local development.
@@ -0,0 +1,136 @@
1
+ import { type MessageInitShape } from "@bufbuild/protobuf";
2
+ import { ConfigSchema, type APIKeyCredentials as WireAPIKeyCredentials, type AuthConfig, type BearerTokenCredentials as WireBearerTokenCredentials, type OAuthCredentials as WireOAuthCredentials, type TokenPairCredentials as WireTokenPairCredentials } from "@sandbox-kit/contracts/client";
3
+ import { ErrorKind as ProtoErrorKind } from "@sandbox-kit/contracts/sandbox";
4
+ import { type ArchiveOptions, type CreateOptions, type CreateResult, type DeleteOptions, type ErrorInfo, type ExitResult, type LifecycleCapability, type PauseOptions, type SandboxInfo, type StartOptions, type StopOptions, type TerminateOptions } from "#contracts/sandbox_data_contracts.js";
5
+ import { type DurationFieldsToMs } from "#internal/duration_ms.js";
6
+ import type { RemapFields } from "#internal/input_remap.js";
7
+ import type { FlattenOneof } from "#internal/oneof_input.js";
8
+ import type { StripProto } from "#internal/strip_proto.js";
9
+ /** Public credential shapes (no protobuf `$typeName` / getters). */
10
+ export type APIKeyCredentials = StripProto<WireAPIKeyCredentials>;
11
+ export type TokenPairCredentials = StripProto<WireTokenPairCredentials>;
12
+ export type BearerTokenCredentials = StripProto<WireBearerTokenCredentials>;
13
+ export type OAuthCredentials = StripProto<WireOAuthCredentials>;
14
+ export type Scope = StripProto<import("@sandbox-kit/contracts/client").Scope>;
15
+ /** Public auth: set exactly one credential variant (no protobuf `{ case, value }`). */
16
+ export type AuthInput = FlattenOneof<NonNullable<AuthConfig["credentials"]>>;
17
+ /**
18
+ * Public client settings (ms timeout, flat auth).
19
+ * Prefer {@link ClientConfig} at construction (`Config` plus `provider`).
20
+ */
21
+ export type Config = DurationFieldsToMs<RemapFields<StripProto<MessageInitShape<typeof ConfigSchema>>, {
22
+ auth: AuthInput;
23
+ }>>;
24
+ export declare const ErrorKind: {
25
+ readonly Unknown: ProtoErrorKind.UNKNOWN;
26
+ readonly InvalidArgument: ProtoErrorKind.INVALID_ARGUMENT;
27
+ readonly Unsupported: ProtoErrorKind.UNSUPPORTED;
28
+ readonly Authentication: ProtoErrorKind.AUTHENTICATION;
29
+ readonly PermissionDenied: ProtoErrorKind.PERMISSION_DENIED;
30
+ readonly NotFound: ProtoErrorKind.NOT_FOUND;
31
+ readonly AlreadyExists: ProtoErrorKind.ALREADY_EXISTS;
32
+ readonly Conflict: ProtoErrorKind.CONFLICT;
33
+ readonly RateLimited: ProtoErrorKind.RATE_LIMITED;
34
+ readonly ResourceExhausted: ProtoErrorKind.RESOURCE_EXHAUSTED;
35
+ readonly Timeout: ProtoErrorKind.TIMEOUT;
36
+ readonly Canceled: ProtoErrorKind.CANCELED;
37
+ readonly Unavailable: ProtoErrorKind.UNAVAILABLE;
38
+ readonly InvalidResponse: ProtoErrorKind.INVALID_RESPONSE;
39
+ readonly Internal: ProtoErrorKind.INTERNAL;
40
+ readonly FailedPrecondition: ProtoErrorKind.FAILED_PRECONDITION;
41
+ };
42
+ export type ErrorKind = (typeof ErrorKind)[keyof typeof ErrorKind];
43
+ export interface OperationOptions {
44
+ readonly signal?: AbortSignal;
45
+ /** Operation deadline in milliseconds. */
46
+ readonly timeout?: number;
47
+ }
48
+ /** Public stop options: Kit call options plus optional force. */
49
+ export type StopCallOptions = OperationOptions & {
50
+ readonly force?: boolean;
51
+ };
52
+ /** Public terminate options: Kit call options plus optional wait. */
53
+ export type TerminateCallOptions = OperationOptions & {
54
+ readonly wait?: boolean;
55
+ };
56
+ /** Public delete options: Kit call options plus optional wait. */
57
+ export type DeleteCallOptions = OperationOptions & {
58
+ readonly wait?: boolean;
59
+ };
60
+ export interface Backend {
61
+ readonly name: string;
62
+ create?(request: CreateOptions, options: OperationOptions): Promise<CreateResult>;
63
+ attach?(id: string, options: OperationOptions): Promise<SandboxInfo>;
64
+ refresh?(id: string, options: OperationOptions): Promise<SandboxInfo>;
65
+ start?(id: string, request: StartOptions, options: OperationOptions): Promise<SandboxInfo>;
66
+ stop?(id: string, request: StopOptions, options: OperationOptions): Promise<SandboxInfo>;
67
+ pause?(id: string, request: PauseOptions, options: OperationOptions): Promise<SandboxInfo>;
68
+ terminate?(id: string, request: TerminateOptions, options: OperationOptions): Promise<ExitResult>;
69
+ archive?(id: string, request: ArchiveOptions, options: OperationOptions): Promise<SandboxInfo>;
70
+ delete?(id: string, request: DeleteOptions, options: OperationOptions): Promise<SandboxInfo>;
71
+ close(options: OperationOptions): Promise<void>;
72
+ closeSandbox?(id: string, options: OperationOptions): Promise<void>;
73
+ capabilities?(info: SandboxInfo): readonly LifecycleCapability[];
74
+ }
75
+ export interface Provider {
76
+ readonly name: string;
77
+ /** Receives public {@link Config}. */
78
+ initialize(config: Config): Backend;
79
+ }
80
+ /** Provider selection stays handwritten and is never part of the portable Config message. */
81
+ export type ClientConfig = Config & {
82
+ readonly provider: Provider;
83
+ };
84
+ export declare class SandboxError extends Error {
85
+ readonly kind: ErrorInfo["kind"];
86
+ readonly provider: string;
87
+ readonly operation: string;
88
+ readonly field: string;
89
+ readonly rule: string | undefined;
90
+ readonly statusCode: number | undefined;
91
+ readonly providerCode: string | undefined;
92
+ readonly providerSource: string | undefined;
93
+ constructor(info: ErrorInfo, options?: ErrorOptions);
94
+ }
95
+ export declare function sandboxError(info: ErrorInfo, cause?: unknown): SandboxError;
96
+ /**
97
+ * Rejects public {@link CreateOptions} the shared contract cannot represent.
98
+ * Materializes wire form privately for Protovalidate. Provider-specific checks
99
+ * remain in each provider adapter.
100
+ */
101
+ export declare function validateCreateOptions(value: CreateOptions, provider?: string, operation?: string): void;
102
+ export declare function validateConfig(value: Config, provider?: string, operation?: string): void;
103
+ interface ClientLifecycle {
104
+ begin(operation: string): () => void;
105
+ isClosed(): boolean;
106
+ }
107
+ declare const sandboxConstructorToken: unique symbol;
108
+ export declare class Sandbox implements AsyncDisposable {
109
+ #private;
110
+ constructor(token: typeof sandboxConstructorToken, backend: Backend, owner: ClientLifecycle, info: SandboxInfo, timeout?: number);
111
+ get id(): string;
112
+ get providerName(): string;
113
+ info(): SandboxInfo;
114
+ capabilities(): readonly LifecycleCapability[];
115
+ supports(capability: LifecycleCapability): boolean;
116
+ refresh(options?: OperationOptions): Promise<SandboxInfo>;
117
+ start(options?: OperationOptions): Promise<SandboxInfo>;
118
+ stop(options?: StopCallOptions): Promise<SandboxInfo>;
119
+ pause(options?: OperationOptions): Promise<SandboxInfo>;
120
+ terminate(options?: TerminateCallOptions): Promise<ExitResult>;
121
+ archive(options?: OperationOptions): Promise<SandboxInfo>;
122
+ delete(options?: DeleteCallOptions): Promise<SandboxInfo>;
123
+ close(options?: OperationOptions): Promise<void>;
124
+ [Symbol.asyncDispose](): Promise<void>;
125
+ }
126
+ export declare class Client implements AsyncDisposable {
127
+ #private;
128
+ constructor(config: ClientConfig);
129
+ get providerName(): string;
130
+ attach(id: string, options?: OperationOptions): Promise<Sandbox>;
131
+ get(id: string, options?: OperationOptions): Promise<Sandbox>;
132
+ create(request?: CreateOptions, options?: OperationOptions): Promise<Sandbox>;
133
+ close(options?: OperationOptions): Promise<void>;
134
+ [Symbol.asyncDispose](): Promise<void>;
135
+ }
136
+ export {};