@brimble/sandbox 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.
Files changed (121) hide show
  1. package/CODEX.md +188 -0
  2. package/PLAN.md +364 -0
  3. package/README.md +147 -0
  4. package/dist/package.json +23 -0
  5. package/dist/src/client.d.ts +23 -0
  6. package/dist/src/client.js +46 -0
  7. package/dist/src/constants.d.ts +14 -0
  8. package/dist/src/constants.js +21 -0
  9. package/dist/src/enums/code-language.d.ts +4 -0
  10. package/dist/src/enums/code-language.js +8 -0
  11. package/dist/src/enums/destroy-reason.d.ts +8 -0
  12. package/dist/src/enums/destroy-reason.js +12 -0
  13. package/dist/src/enums/destroy-timeout.d.ts +8 -0
  14. package/dist/src/enums/destroy-timeout.js +12 -0
  15. package/dist/src/enums/index.d.ts +7 -0
  16. package/dist/src/enums/index.js +17 -0
  17. package/dist/src/enums/sandbox-status.d.ts +9 -0
  18. package/dist/src/enums/sandbox-status.js +13 -0
  19. package/dist/src/enums/snapshot-mode.d.ts +4 -0
  20. package/dist/src/enums/snapshot-mode.js +8 -0
  21. package/dist/src/enums/snapshot-status.d.ts +5 -0
  22. package/dist/src/enums/snapshot-status.js +9 -0
  23. package/dist/src/enums/volume-type.d.ts +3 -0
  24. package/dist/src/enums/volume-type.js +7 -0
  25. package/dist/src/errors/index.d.ts +2 -0
  26. package/dist/src/errors/index.js +9 -0
  27. package/dist/src/errors/sandbox-api-error.d.ts +29 -0
  28. package/dist/src/errors/sandbox-api-error.js +48 -0
  29. package/dist/src/index.d.ts +10 -0
  30. package/dist/src/index.js +40 -0
  31. package/dist/src/resources/exec.d.ts +19 -0
  32. package/dist/src/resources/exec.js +45 -0
  33. package/dist/src/resources/files.d.ts +16 -0
  34. package/dist/src/resources/files.js +41 -0
  35. package/dist/src/resources/index.d.ts +8 -0
  36. package/dist/src/resources/index.js +20 -0
  37. package/dist/src/resources/path.d.ts +7 -0
  38. package/dist/src/resources/path.js +19 -0
  39. package/dist/src/resources/sandbox-handle.d.ts +78 -0
  40. package/dist/src/resources/sandbox-handle.js +151 -0
  41. package/dist/src/resources/sandboxes.d.ts +64 -0
  42. package/dist/src/resources/sandboxes.js +224 -0
  43. package/dist/src/resources/scoped-sandbox.d.ts +39 -0
  44. package/dist/src/resources/scoped-sandbox.js +51 -0
  45. package/dist/src/resources/snapshots.d.ts +26 -0
  46. package/dist/src/resources/snapshots.js +88 -0
  47. package/dist/src/resources/stats.d.ts +11 -0
  48. package/dist/src/resources/stats.js +26 -0
  49. package/dist/src/resources/volumes.d.ts +21 -0
  50. package/dist/src/resources/volumes.js +80 -0
  51. package/dist/src/transport/auth.d.ts +2 -0
  52. package/dist/src/transport/auth.js +7 -0
  53. package/dist/src/transport/http.d.ts +73 -0
  54. package/dist/src/transport/http.js +354 -0
  55. package/dist/src/transport/pagination.d.ts +3 -0
  56. package/dist/src/transport/pagination.js +11 -0
  57. package/dist/src/types/exec.d.ts +34 -0
  58. package/dist/src/types/exec.js +2 -0
  59. package/dist/src/types/files.d.ts +1 -0
  60. package/dist/src/types/files.js +2 -0
  61. package/dist/src/types/index.d.ts +9 -0
  62. package/dist/src/types/index.js +2 -0
  63. package/dist/src/types/pagination.d.ts +14 -0
  64. package/dist/src/types/pagination.js +2 -0
  65. package/dist/src/types/region.d.ts +17 -0
  66. package/dist/src/types/region.js +2 -0
  67. package/dist/src/types/sandbox.d.ts +90 -0
  68. package/dist/src/types/sandbox.js +2 -0
  69. package/dist/src/types/snapshot.d.ts +15 -0
  70. package/dist/src/types/snapshot.js +2 -0
  71. package/dist/src/types/stats.d.ts +31 -0
  72. package/dist/src/types/stats.js +2 -0
  73. package/dist/src/types/template.d.ts +5 -0
  74. package/dist/src/types/template.js +2 -0
  75. package/dist/src/types/volume.d.ts +24 -0
  76. package/dist/src/types/volume.js +2 -0
  77. package/package.json +26 -0
  78. package/src/client.ts +61 -0
  79. package/src/constants.ts +17 -0
  80. package/src/enums/code-language.ts +4 -0
  81. package/src/enums/destroy-reason.ts +8 -0
  82. package/src/enums/destroy-timeout.ts +8 -0
  83. package/src/enums/index.ts +7 -0
  84. package/src/enums/sandbox-status.ts +9 -0
  85. package/src/enums/snapshot-mode.ts +4 -0
  86. package/src/enums/snapshot-status.ts +5 -0
  87. package/src/enums/volume-type.ts +3 -0
  88. package/src/errors/index.ts +2 -0
  89. package/src/errors/sandbox-api-error.ts +54 -0
  90. package/src/index.ts +71 -0
  91. package/src/resources/exec.ts +56 -0
  92. package/src/resources/files.ts +46 -0
  93. package/src/resources/index.ts +8 -0
  94. package/src/resources/path.ts +16 -0
  95. package/src/resources/sandbox-handle.ts +215 -0
  96. package/src/resources/sandboxes.ts +297 -0
  97. package/src/resources/scoped-sandbox.ts +65 -0
  98. package/src/resources/snapshots.ts +104 -0
  99. package/src/resources/stats.ts +30 -0
  100. package/src/resources/volumes.ts +95 -0
  101. package/src/transport/auth.ts +4 -0
  102. package/src/transport/http.ts +501 -0
  103. package/src/transport/pagination.ts +10 -0
  104. package/src/types/exec.ts +42 -0
  105. package/src/types/files.ts +1 -0
  106. package/src/types/index.ts +23 -0
  107. package/src/types/pagination.ts +16 -0
  108. package/src/types/region.ts +19 -0
  109. package/src/types/sandbox.ts +103 -0
  110. package/src/types/snapshot.ts +17 -0
  111. package/src/types/stats.ts +35 -0
  112. package/src/types/template.ts +5 -0
  113. package/src/types/volume.ts +26 -0
  114. package/test/integration/sandbox.integration.test.ts +269 -0
  115. package/test/unit/client.test.ts +87 -0
  116. package/test/unit/sandboxes.test.ts +69 -0
  117. package/test/unit/transport.test.ts +126 -0
  118. package/test/unit/volumes.test.ts +122 -0
  119. package/tsconfig.json +16 -0
  120. package/vitest.config.ts +12 -0
  121. package/vitest.integration.config.ts +15 -0
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpTransport = void 0;
4
+ const constants_1 = require("../constants");
5
+ const errors_1 = require("../errors");
6
+ const auth_1 = require("./auth");
7
+ function isRecord(value) {
8
+ return typeof value === 'object' && value !== null;
9
+ }
10
+ function hasMessage(value) {
11
+ return isRecord(value) && typeof value.message === 'string';
12
+ }
13
+ function isEnvelope(value) {
14
+ return hasMessage(value);
15
+ }
16
+ function maybeJoinSignal(signal, timeoutMs) {
17
+ if (!signal) {
18
+ return { signal: AbortSignal.timeout(timeoutMs), cleanup: () => { } };
19
+ }
20
+ const timeoutController = new AbortController();
21
+ const timeoutId = setTimeout(() => {
22
+ timeoutController.abort(new DOMException('The operation timed out.', 'AbortError'));
23
+ }, timeoutMs);
24
+ const mergedController = new AbortController();
25
+ const onCallerAbort = () => {
26
+ mergedController.abort(signal.reason);
27
+ };
28
+ const onTimeoutAbort = () => {
29
+ mergedController.abort(timeoutController.signal.reason);
30
+ };
31
+ if (signal.aborted) {
32
+ mergedController.abort(signal.reason);
33
+ }
34
+ else {
35
+ signal.addEventListener('abort', onCallerAbort, { once: true });
36
+ }
37
+ timeoutController.signal.addEventListener('abort', onTimeoutAbort, { once: true });
38
+ const cleanup = () => {
39
+ clearTimeout(timeoutId);
40
+ signal.removeEventListener('abort', onCallerAbort);
41
+ timeoutController.signal.removeEventListener('abort', onTimeoutAbort);
42
+ };
43
+ return { signal: mergedController.signal, cleanup };
44
+ }
45
+ async function parseResponseBody(response) {
46
+ const contentType = response.headers.get('content-type') ?? '';
47
+ if (contentType.includes('application/json')) {
48
+ return response.json();
49
+ }
50
+ const text = await response.text();
51
+ return text.length > 0 ? text : null;
52
+ }
53
+ function buildUrl(baseUrl, endpoint, query) {
54
+ const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
55
+ const normalizedPath = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
56
+ const url = new URL(`${normalizedBaseUrl}${normalizedPath}`);
57
+ if (query) {
58
+ url.search = query.toString();
59
+ }
60
+ return url.toString();
61
+ }
62
+ function normalizeRetryConfig(retry) {
63
+ return {
64
+ maxAttempts: Math.max(1, retry?.maxAttempts ?? constants_1.DEFAULT_RETRY_MAX_ATTEMPTS),
65
+ baseDelayMs: Math.max(0, retry?.baseDelayMs ?? constants_1.DEFAULT_RETRY_BASE_DELAY_MS),
66
+ maxDelayMs: Math.max(0, retry?.maxDelayMs ?? constants_1.DEFAULT_RETRY_MAX_DELAY_MS),
67
+ retryStatuses: retry?.retryStatuses ?? [...constants_1.DEFAULT_RETRY_STATUSES],
68
+ retryMethods: retry?.retryMethods ?? ['GET', 'DELETE', 'PUT'],
69
+ };
70
+ }
71
+ function mergeRetryConfig(base, override) {
72
+ if (override === false) {
73
+ return {
74
+ ...base,
75
+ maxAttempts: 1,
76
+ };
77
+ }
78
+ if (!override) {
79
+ return base;
80
+ }
81
+ return normalizeRetryConfig({
82
+ maxAttempts: override.maxAttempts ?? base.maxAttempts,
83
+ baseDelayMs: override.baseDelayMs ?? base.baseDelayMs,
84
+ maxDelayMs: override.maxDelayMs ?? base.maxDelayMs,
85
+ retryStatuses: override.retryStatuses ?? base.retryStatuses,
86
+ retryMethods: override.retryMethods ?? base.retryMethods,
87
+ });
88
+ }
89
+ function isAbortError(error) {
90
+ return error instanceof DOMException && error.name === 'AbortError';
91
+ }
92
+ function canRetryByMethod(method, retryMethods, idempotencyKey) {
93
+ if (retryMethods.includes(method)) {
94
+ return true;
95
+ }
96
+ if (method === 'POST' && idempotencyKey) {
97
+ return true;
98
+ }
99
+ return false;
100
+ }
101
+ function canRetryBody(body) {
102
+ if (!body) {
103
+ return true;
104
+ }
105
+ if (typeof body === 'string') {
106
+ return true;
107
+ }
108
+ if (Buffer.isBuffer(body) || body instanceof Uint8Array) {
109
+ return true;
110
+ }
111
+ return false;
112
+ }
113
+ function computeRetryDelayMs(attempt, baseDelayMs, maxDelayMs) {
114
+ const exponent = Math.max(0, attempt - 1);
115
+ const delayMs = baseDelayMs * (2 ** exponent);
116
+ return Math.min(maxDelayMs, delayMs);
117
+ }
118
+ async function sleep(ms) {
119
+ if (ms <= 0) {
120
+ return;
121
+ }
122
+ await new Promise((resolve) => {
123
+ setTimeout(resolve, ms);
124
+ });
125
+ }
126
+ function parseRetryAfterSeconds(value) {
127
+ if (!value) {
128
+ return null;
129
+ }
130
+ const asNumber = Number(value);
131
+ if (Number.isFinite(asNumber)) {
132
+ return asNumber;
133
+ }
134
+ return null;
135
+ }
136
+ function getRequestId(response) {
137
+ return response.headers.get('x-request-id') ?? response.headers.get('x-correlation-id') ?? null;
138
+ }
139
+ class HttpTransport {
140
+ baseUrl;
141
+ apiKey;
142
+ timeoutMs;
143
+ fetchImpl;
144
+ retry;
145
+ /** Create a transport used by all SDK resources. */
146
+ constructor(config) {
147
+ this.baseUrl = config.baseUrl;
148
+ this.apiKey = config.apiKey;
149
+ this.timeoutMs = config.timeoutMs ?? constants_1.DEFAULT_TIMEOUT_MS;
150
+ this.fetchImpl = config.fetchImpl ?? globalThis.fetch;
151
+ this.retry = normalizeRetryConfig(config.retry);
152
+ }
153
+ /**
154
+ * Send a JSON request and return the unwrapped `data` payload.
155
+ * If the endpoint returns 204, this resolves to `undefined`.
156
+ */
157
+ async requestJson(args) {
158
+ const headers = args.body !== undefined ? { 'content-type': 'application/json', ...(args.headers ?? {}) } : args.headers;
159
+ const response = await this.executeRequest({
160
+ endpoint: args.endpoint,
161
+ method: args.method,
162
+ query: args.query,
163
+ body: args.body !== undefined ? JSON.stringify(args.body) : undefined,
164
+ headers,
165
+ signal: args.signal,
166
+ timeoutMs: args.timeoutMs,
167
+ idempotencyKey: args.idempotencyKey,
168
+ retry: args.retry,
169
+ });
170
+ if (response.status === 204) {
171
+ return undefined;
172
+ }
173
+ const payload = await parseResponseBody(response);
174
+ if (!response.ok) {
175
+ throw this.toApiError(response, args.method, args.endpoint, payload);
176
+ }
177
+ if (isEnvelope(payload)) {
178
+ if ('data' in payload) {
179
+ return payload.data;
180
+ }
181
+ return payload;
182
+ }
183
+ return payload;
184
+ }
185
+ /**
186
+ * Send a binary upload request (for file writes).
187
+ * Returns when the API acknowledges success.
188
+ */
189
+ async requestBinary(args) {
190
+ const response = await this.executeRequest({
191
+ endpoint: args.endpoint,
192
+ method: args.method,
193
+ query: args.query,
194
+ body: args.body,
195
+ headers: args.headers,
196
+ signal: args.signal,
197
+ timeoutMs: args.timeoutMs,
198
+ idempotencyKey: args.idempotencyKey,
199
+ retry: args.retry,
200
+ });
201
+ if (response.ok || response.status === 204) {
202
+ return;
203
+ }
204
+ const payload = await parseResponseBody(response);
205
+ throw this.toApiError(response, args.method, args.endpoint, payload);
206
+ }
207
+ /**
208
+ * Send a JSON request and return the raw response stream.
209
+ * Used for endpoints that stream SSE frames (`text/event-stream`).
210
+ */
211
+ async requestJsonStream(args) {
212
+ const headers = args.body !== undefined ? { 'content-type': 'application/json', ...(args.headers ?? {}) } : args.headers;
213
+ const response = await this.executeRequest({
214
+ endpoint: args.endpoint,
215
+ method: args.method,
216
+ query: args.query,
217
+ body: args.body !== undefined ? JSON.stringify(args.body) : undefined,
218
+ headers,
219
+ signal: args.signal,
220
+ timeoutMs: args.timeoutMs,
221
+ idempotencyKey: args.idempotencyKey,
222
+ retry: args.retry,
223
+ });
224
+ if (!response.ok) {
225
+ const payload = await parseResponseBody(response);
226
+ throw this.toApiError(response, args.method, args.endpoint, payload);
227
+ }
228
+ if (!response.body) {
229
+ throw new errors_1.SandboxApiError({
230
+ status: response.status,
231
+ message: 'Expected a response stream but received an empty body',
232
+ endpoint: `${args.method} ${args.endpoint}`,
233
+ responseBody: null,
234
+ requestId: getRequestId(response),
235
+ });
236
+ }
237
+ return response.body;
238
+ }
239
+ /**
240
+ * Request a binary response stream (for file downloads).
241
+ * Throws if the API returns an error status.
242
+ */
243
+ async requestStream(args) {
244
+ const response = await this.executeRequest({
245
+ endpoint: args.endpoint,
246
+ method: args.method,
247
+ query: args.query,
248
+ signal: args.signal,
249
+ timeoutMs: args.timeoutMs,
250
+ idempotencyKey: args.idempotencyKey,
251
+ retry: args.retry,
252
+ });
253
+ if (!response.ok) {
254
+ const payload = await parseResponseBody(response);
255
+ throw this.toApiError(response, args.method, args.endpoint, payload);
256
+ }
257
+ if (!response.body) {
258
+ throw new errors_1.SandboxApiError({
259
+ status: response.status,
260
+ message: 'Expected a response stream but received an empty body',
261
+ endpoint: `${args.method} ${args.endpoint}`,
262
+ responseBody: null,
263
+ requestId: getRequestId(response),
264
+ });
265
+ }
266
+ return response.body;
267
+ }
268
+ async executeRequest(args) {
269
+ const timeoutMs = args.timeoutMs ?? this.timeoutMs;
270
+ const retryConfig = mergeRetryConfig(this.retry, args.retry);
271
+ const canRetryMethod = canRetryByMethod(args.method, retryConfig.retryMethods, args.idempotencyKey);
272
+ const replayableBody = canRetryBody(args.body);
273
+ let lastError;
274
+ for (let attempt = 1; attempt <= retryConfig.maxAttempts; attempt += 1) {
275
+ const { signal, cleanup } = maybeJoinSignal(args.signal, timeoutMs);
276
+ try {
277
+ const response = await this.fetchImpl(buildUrl(this.baseUrl, args.endpoint, args.query), {
278
+ method: args.method,
279
+ headers: {
280
+ 'x-brimble-key': (0, auth_1.buildApiKeyHeader)(this.apiKey),
281
+ source: 'sdk-package',
282
+ 'source-version': constants_1.SDK_PACKAGE_VERSION,
283
+ ...(args.idempotencyKey ? { 'idempotency-key': args.idempotencyKey } : {}),
284
+ ...(args.headers ?? {}),
285
+ },
286
+ body: args.body,
287
+ signal,
288
+ });
289
+ const shouldRetry = attempt < retryConfig.maxAttempts &&
290
+ canRetryMethod &&
291
+ replayableBody &&
292
+ retryConfig.retryStatuses.includes(response.status) &&
293
+ !signal.aborted;
294
+ if (shouldRetry) {
295
+ await sleep(computeRetryDelayMs(attempt, retryConfig.baseDelayMs, retryConfig.maxDelayMs));
296
+ continue;
297
+ }
298
+ return response;
299
+ }
300
+ catch (error) {
301
+ lastError = error;
302
+ const shouldRetry = attempt < retryConfig.maxAttempts &&
303
+ canRetryMethod &&
304
+ replayableBody &&
305
+ !isAbortError(error) &&
306
+ !(args.signal?.aborted ?? false);
307
+ if (!shouldRetry) {
308
+ throw error;
309
+ }
310
+ await sleep(computeRetryDelayMs(attempt, retryConfig.baseDelayMs, retryConfig.maxDelayMs));
311
+ }
312
+ finally {
313
+ cleanup();
314
+ }
315
+ }
316
+ if (lastError) {
317
+ throw lastError;
318
+ }
319
+ throw new Error('HTTP request failed before receiving a response.');
320
+ }
321
+ toApiError(response, method, endpoint, responseBody) {
322
+ let message = response.statusText || 'Sandbox API request failed';
323
+ if (hasMessage(responseBody)) {
324
+ message = responseBody.message;
325
+ }
326
+ else if (typeof responseBody === 'string' && responseBody.trim().length > 0) {
327
+ message = responseBody;
328
+ }
329
+ const baseArgs = {
330
+ status: response.status,
331
+ message,
332
+ endpoint: `${method} ${endpoint}`,
333
+ responseBody,
334
+ requestId: getRequestId(response),
335
+ };
336
+ if (response.status === 401 || response.status === 403) {
337
+ return new errors_1.AuthError(baseArgs);
338
+ }
339
+ if (response.status === 400 || response.status === 422) {
340
+ return new errors_1.ValidationError(baseArgs);
341
+ }
342
+ if (response.status === 404) {
343
+ return new errors_1.NotFoundError(baseArgs);
344
+ }
345
+ if (response.status === 429) {
346
+ return new errors_1.RateLimitError({
347
+ ...baseArgs,
348
+ retryAfterSeconds: parseRetryAfterSeconds(response.headers.get('retry-after')),
349
+ });
350
+ }
351
+ return new errors_1.SandboxApiError(baseArgs);
352
+ }
353
+ }
354
+ exports.HttpTransport = HttpTransport;
@@ -0,0 +1,3 @@
1
+ import type { Pagination } from '../types';
2
+ /** Convert pagination inputs into query params with sensible defaults. */
3
+ export declare function toPaginationQuery(pagination?: Pagination): URLSearchParams;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toPaginationQuery = toPaginationQuery;
4
+ const constants_1 = require("../constants");
5
+ /** Convert pagination inputs into query params with sensible defaults. */
6
+ function toPaginationQuery(pagination = {}) {
7
+ const params = new URLSearchParams();
8
+ params.set('page', String(pagination.page ?? constants_1.DEFAULT_PAGE));
9
+ params.set('limit', String(pagination.limit ?? constants_1.DEFAULT_PAGE_LIMIT));
10
+ return params;
11
+ }
@@ -0,0 +1,34 @@
1
+ import { CodeLanguage } from '../enums';
2
+ export type ExecInput = {
3
+ cmd: string;
4
+ timeout_seconds?: number;
5
+ cwd?: string;
6
+ stream?: boolean;
7
+ };
8
+ export type CodeInput = {
9
+ language: CodeLanguage;
10
+ code: string;
11
+ timeout_seconds?: number;
12
+ cwd?: string;
13
+ stream?: boolean;
14
+ };
15
+ export type ExecResult = {
16
+ stdout: string;
17
+ stderr: string;
18
+ exit_code: number;
19
+ duration_ms: number;
20
+ };
21
+ export type ExecStreamFrame = {
22
+ type: 'stdout';
23
+ data: string;
24
+ } | {
25
+ type: 'stderr';
26
+ data: string;
27
+ } | {
28
+ type: 'done';
29
+ exit_code: number;
30
+ duration_ms: number;
31
+ } | {
32
+ type: 'error';
33
+ message: string;
34
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type FileUploadBody = ReadableStream<Uint8Array> | Buffer | Uint8Array;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ export type { CodeInput, ExecInput, ExecResult, ExecStreamFrame } from './exec';
2
+ export type { FileUploadBody } from './files';
3
+ export type { Paginated, Pagination, TeamScopedPagination } from './pagination';
4
+ export type { RegionSummary, SandboxRegion, SandboxRegionsResult } from './region';
5
+ export type { AckMessage, CreateSandboxInput, CreateSandboxRequest, CreateSandboxResult, CreateSandboxWithVolumeInput, CreateSandboxWithVolumeResult, Sandbox, SandboxReadyRequestOptions, SandboxRegionInput, SandboxRuntimeOptions, SandboxSpecs, WaitPreference, WaitUntilReadyOptions, } from './sandbox';
6
+ export type { CreateSnapshotInput, Snapshot } from './snapshot';
7
+ export type { Stats, StatsAverageNetwork, StatsAverageNumeric, StatsQuery, StatsTimelinePoint } from './stats';
8
+ export type { SandboxTemplate } from './template';
9
+ export type { CreateVolumeInput, Volume } from './volume';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ export type Pagination = {
2
+ page?: number;
3
+ limit?: number;
4
+ };
5
+ export type TeamScopedPagination = Pagination & {
6
+ teamId?: string;
7
+ };
8
+ export type Paginated<T> = {
9
+ data: T[];
10
+ totalCount: number;
11
+ currentPage: number;
12
+ totalPages: number;
13
+ limit: number;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ export type RegionSummary = {
2
+ id: string;
3
+ name: string;
4
+ country: string;
5
+ continent: string | null;
6
+ provider: string;
7
+ is_paid: boolean;
8
+ };
9
+ export type SandboxRegion = {
10
+ id: string;
11
+ name: string;
12
+ country: string;
13
+ continent: string | null;
14
+ };
15
+ export type SandboxRegionsResult = {
16
+ regions: SandboxRegion[];
17
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,90 @@
1
+ import { DestroyReason, DestroyTimeout, SandboxStatus, SnapshotMode } from '../enums';
2
+ import type { RequestOptions } from '../transport/http';
3
+ import type { RegionSummary } from './region';
4
+ import type { CreateVolumeInput, Volume } from './volume';
5
+ export type SandboxSpecs = {
6
+ cpu?: number;
7
+ memory?: number;
8
+ disk?: number;
9
+ };
10
+ export type SandboxRegionInput = string | 'auto';
11
+ export type CreateSandboxInput = {
12
+ name?: string;
13
+ template?: string;
14
+ teamId?: string;
15
+ environmentId?: string;
16
+ region?: string;
17
+ specs?: SandboxSpecs;
18
+ autoDestroy?: boolean;
19
+ destroyTimeout?: DestroyTimeout;
20
+ oneShot?: boolean;
21
+ blockOutbound?: boolean;
22
+ persistent?: boolean;
23
+ persistentDiskGB?: number;
24
+ volumeId?: string;
25
+ fromSnapshot?: string;
26
+ snapshotMode?: SnapshotMode;
27
+ snapshotFrequency?: string;
28
+ };
29
+ export type CreateSandboxRequest = Omit<CreateSandboxInput, 'region'> & {
30
+ region?: SandboxRegionInput;
31
+ };
32
+ export type CreateSandboxResult = {
33
+ id: string;
34
+ name: string;
35
+ template: string;
36
+ status: SandboxStatus;
37
+ created_at: string;
38
+ expires_at: string;
39
+ };
40
+ export type Sandbox = {
41
+ id: string;
42
+ name: string;
43
+ template: string;
44
+ status: SandboxStatus;
45
+ region: RegionSummary | string;
46
+ specs: SandboxSpecs;
47
+ team: string | null;
48
+ project_environment: string | null;
49
+ auto_destroy: boolean;
50
+ destroy_timeout: DestroyTimeout | null;
51
+ one_shot: boolean;
52
+ block_outbound: boolean;
53
+ persistent: boolean;
54
+ persistent_disk_gb: number | null;
55
+ paused_at: string | null;
56
+ from_snapshot: string | null;
57
+ snapshot_mode: SnapshotMode;
58
+ snapshot_frequency: string | null;
59
+ created_at: string;
60
+ last_activity_at: string;
61
+ expires_at: string;
62
+ destroyed_at: string | null;
63
+ destroy_reason: DestroyReason | null;
64
+ };
65
+ export type AckMessage = {
66
+ message: string;
67
+ };
68
+ export type WaitUntilReadyOptions = {
69
+ timeoutMs?: number;
70
+ pollIntervalMs?: number;
71
+ signal?: AbortSignal;
72
+ };
73
+ export type WaitPreference = boolean | WaitUntilReadyOptions;
74
+ export type SandboxRuntimeOptions = RequestOptions & {
75
+ waitUntilReady?: WaitPreference;
76
+ };
77
+ export type SandboxReadyRequestOptions = {
78
+ request?: RequestOptions;
79
+ wait?: WaitUntilReadyOptions;
80
+ };
81
+ export type CreateSandboxWithVolumeInput = {
82
+ sandbox: Omit<CreateSandboxRequest, 'volumeId' | 'persistent' | 'persistentDiskGB'>;
83
+ volume: Omit<CreateVolumeInput, 'region'> & {
84
+ region?: string;
85
+ };
86
+ };
87
+ export type CreateSandboxWithVolumeResult = {
88
+ sandbox: CreateSandboxResult;
89
+ volume: Volume;
90
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,15 @@
1
+ import { SnapshotStatus } from '../enums';
2
+ export type CreateSnapshotInput = {
3
+ name: string;
4
+ };
5
+ export type Snapshot = {
6
+ id: string;
7
+ sandbox_id: string;
8
+ name: string;
9
+ image_tag: string;
10
+ source_template: string;
11
+ status: SnapshotStatus;
12
+ failure_reason: string | null;
13
+ size_bytes: number | null;
14
+ created_at: string;
15
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,31 @@
1
+ export type StatsAverageNumeric = {
2
+ totalInPercentage: number;
3
+ size: number;
4
+ };
5
+ export type StatsAverageNetwork = {
6
+ value?: number | null;
7
+ total?: number | null;
8
+ totalInPercentage?: number | null;
9
+ bytesPerSecond?: number | null;
10
+ };
11
+ export type StatsTimelinePoint = {
12
+ date: string;
13
+ memory: number;
14
+ cpu: number;
15
+ network: {
16
+ bytesPerSecond: number | null;
17
+ };
18
+ };
19
+ export type Stats = {
20
+ average: {
21
+ memory: StatsAverageNumeric;
22
+ cpu: StatsAverageNumeric;
23
+ network: StatsAverageNetwork;
24
+ };
25
+ replicaCount: number;
26
+ results: StatsTimelinePoint[];
27
+ responseTime: unknown;
28
+ };
29
+ export type StatsQuery = {
30
+ hoursAgo?: number;
31
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export type SandboxTemplate = {
2
+ name: string;
3
+ display_name: string;
4
+ description: string;
5
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,24 @@
1
+ import { VolumeType } from '../enums';
2
+ import type { RegionSummary } from './region';
3
+ export type CreateVolumeInput = {
4
+ name: string;
5
+ sizeGB: number;
6
+ region: string;
7
+ type?: VolumeType;
8
+ teamId?: string;
9
+ };
10
+ export type Volume = {
11
+ id: string;
12
+ name: string;
13
+ type: VolumeType;
14
+ team: string | null;
15
+ csi_volume_id: string | null;
16
+ size: number;
17
+ region: RegionSummary | null;
18
+ mount_path: string | null;
19
+ attached_sandbox_id: string | null;
20
+ attached_project_id: string | null;
21
+ last_attached_at: string | null;
22
+ created_at: string | null;
23
+ updated_at: string | null;
24
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });