@cloudflare/sandbox 0.0.0-d86b60e → 0.0.0-da2cfb8

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 (104) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/Dockerfile +91 -50
  3. package/README.md +88 -772
  4. package/dist/chunk-BFVUNTP4.js +104 -0
  5. package/dist/chunk-BFVUNTP4.js.map +1 -0
  6. package/dist/chunk-EKSWCBCA.js +86 -0
  7. package/dist/chunk-EKSWCBCA.js.map +1 -0
  8. package/dist/chunk-JXZMAU2C.js +559 -0
  9. package/dist/chunk-JXZMAU2C.js.map +1 -0
  10. package/dist/chunk-PG2V52M2.js +2420 -0
  11. package/dist/chunk-PG2V52M2.js.map +1 -0
  12. package/dist/chunk-QDBKO3CL.js +7 -0
  13. package/dist/chunk-QDBKO3CL.js.map +1 -0
  14. package/dist/chunk-Z532A7QC.js +78 -0
  15. package/dist/chunk-Z532A7QC.js.map +1 -0
  16. package/dist/file-stream.d.ts +43 -0
  17. package/dist/file-stream.js +9 -0
  18. package/dist/file-stream.js.map +1 -0
  19. package/dist/index.d.ts +9 -0
  20. package/dist/index.js +67 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/interpreter.d.ts +33 -0
  23. package/dist/interpreter.js +8 -0
  24. package/dist/interpreter.js.map +1 -0
  25. package/dist/request-handler.d.ts +18 -0
  26. package/dist/request-handler.js +13 -0
  27. package/dist/request-handler.js.map +1 -0
  28. package/dist/sandbox-DMlNr93l.d.ts +596 -0
  29. package/dist/sandbox.d.ts +4 -0
  30. package/dist/sandbox.js +13 -0
  31. package/dist/sandbox.js.map +1 -0
  32. package/dist/security.d.ts +31 -0
  33. package/dist/security.js +13 -0
  34. package/dist/security.js.map +1 -0
  35. package/dist/sse-parser.d.ts +28 -0
  36. package/dist/sse-parser.js +11 -0
  37. package/dist/sse-parser.js.map +1 -0
  38. package/dist/version.d.ts +8 -0
  39. package/dist/version.js +7 -0
  40. package/dist/version.js.map +1 -0
  41. package/package.json +12 -4
  42. package/src/clients/base-client.ts +280 -0
  43. package/src/clients/command-client.ts +115 -0
  44. package/src/clients/file-client.ts +269 -0
  45. package/src/clients/git-client.ts +92 -0
  46. package/src/clients/index.ts +64 -0
  47. package/src/{interpreter-client.ts → clients/interpreter-client.ts} +148 -171
  48. package/src/clients/port-client.ts +105 -0
  49. package/src/clients/process-client.ts +177 -0
  50. package/src/clients/sandbox-client.ts +41 -0
  51. package/src/clients/types.ts +84 -0
  52. package/src/clients/utility-client.ts +119 -0
  53. package/src/errors/adapter.ts +180 -0
  54. package/src/errors/classes.ts +469 -0
  55. package/src/errors/index.ts +105 -0
  56. package/src/file-stream.ts +164 -0
  57. package/src/index.ts +81 -63
  58. package/src/interpreter.ts +17 -8
  59. package/src/request-handler.ts +69 -43
  60. package/src/sandbox.ts +781 -531
  61. package/src/security.ts +14 -23
  62. package/src/sse-parser.ts +4 -8
  63. package/src/version.ts +6 -0
  64. package/startup.sh +3 -0
  65. package/tests/base-client.test.ts +328 -0
  66. package/tests/command-client.test.ts +407 -0
  67. package/tests/file-client.test.ts +643 -0
  68. package/tests/file-stream.test.ts +306 -0
  69. package/tests/get-sandbox.test.ts +110 -0
  70. package/tests/git-client.test.ts +328 -0
  71. package/tests/port-client.test.ts +301 -0
  72. package/tests/process-client.test.ts +658 -0
  73. package/tests/sandbox.test.ts +465 -0
  74. package/tests/sse-parser.test.ts +290 -0
  75. package/tests/utility-client.test.ts +332 -0
  76. package/tests/version.test.ts +16 -0
  77. package/tests/wrangler.jsonc +35 -0
  78. package/tsconfig.json +9 -1
  79. package/vitest.config.ts +31 -0
  80. package/container_src/bun.lock +0 -76
  81. package/container_src/circuit-breaker.ts +0 -121
  82. package/container_src/control-process.ts +0 -784
  83. package/container_src/handler/exec.ts +0 -185
  84. package/container_src/handler/file.ts +0 -406
  85. package/container_src/handler/git.ts +0 -130
  86. package/container_src/handler/ports.ts +0 -314
  87. package/container_src/handler/process.ts +0 -568
  88. package/container_src/handler/session.ts +0 -92
  89. package/container_src/index.ts +0 -592
  90. package/container_src/interpreter-service.ts +0 -276
  91. package/container_src/isolation.ts +0 -1049
  92. package/container_src/mime-processor.ts +0 -255
  93. package/container_src/package.json +0 -18
  94. package/container_src/runtime/executors/javascript/node_executor.ts +0 -123
  95. package/container_src/runtime/executors/python/ipython_executor.py +0 -338
  96. package/container_src/runtime/executors/typescript/ts_executor.ts +0 -138
  97. package/container_src/runtime/process-pool.ts +0 -464
  98. package/container_src/shell-escape.ts +0 -42
  99. package/container_src/startup.sh +0 -11
  100. package/container_src/types.ts +0 -131
  101. package/src/client.ts +0 -1009
  102. package/src/errors.ts +0 -219
  103. package/src/interpreter-types.ts +0 -390
  104. package/src/types.ts +0 -502
@@ -0,0 +1,269 @@
1
+ import type {
2
+ DeleteFileResult,
3
+ ListFilesOptions,
4
+ ListFilesResult,
5
+ MkdirResult,
6
+ MoveFileResult,
7
+ ReadFileResult,
8
+ RenameFileResult,
9
+ WriteFileResult
10
+ } from '@repo/shared';
11
+ import { BaseHttpClient } from './base-client';
12
+ import type { HttpClientOptions, SessionRequest } from './types';
13
+
14
+ /**
15
+ * Request interface for creating directories
16
+ */
17
+ export interface MkdirRequest extends SessionRequest {
18
+ path: string;
19
+ recursive?: boolean;
20
+ }
21
+
22
+ /**
23
+ * Request interface for writing files
24
+ */
25
+ export interface WriteFileRequest extends SessionRequest {
26
+ path: string;
27
+ content: string;
28
+ encoding?: string;
29
+ }
30
+
31
+ /**
32
+ * Request interface for reading files
33
+ */
34
+ export interface ReadFileRequest extends SessionRequest {
35
+ path: string;
36
+ encoding?: string;
37
+ }
38
+
39
+ /**
40
+ * Request interface for file operations (delete, rename, move)
41
+ */
42
+ export interface FileOperationRequest extends SessionRequest {
43
+ path: string;
44
+ newPath?: string; // For rename/move operations
45
+ }
46
+
47
+ /**
48
+ * Client for file system operations
49
+ */
50
+ export class FileClient extends BaseHttpClient {
51
+
52
+ /**
53
+ * Create a directory
54
+ * @param path - Directory path to create
55
+ * @param sessionId - The session ID for this operation
56
+ * @param options - Optional settings (recursive)
57
+ */
58
+ async mkdir(
59
+ path: string,
60
+ sessionId: string,
61
+ options?: { recursive?: boolean }
62
+ ): Promise<MkdirResult> {
63
+ try {
64
+ const data = {
65
+ path,
66
+ sessionId,
67
+ recursive: options?.recursive ?? false,
68
+ };
69
+
70
+ const response = await this.post<MkdirResult>('/api/mkdir', data);
71
+
72
+ this.logSuccess('Directory created', `${path} (recursive: ${data.recursive})`);
73
+ return response;
74
+ } catch (error) {
75
+ this.logError('mkdir', error);
76
+ throw error;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Write content to a file
82
+ * @param path - File path to write to
83
+ * @param content - Content to write
84
+ * @param sessionId - The session ID for this operation
85
+ * @param options - Optional settings (encoding)
86
+ */
87
+ async writeFile(
88
+ path: string,
89
+ content: string,
90
+ sessionId: string,
91
+ options?: { encoding?: string }
92
+ ): Promise<WriteFileResult> {
93
+ try {
94
+ const data = {
95
+ path,
96
+ content,
97
+ sessionId,
98
+ encoding: options?.encoding ?? 'utf8',
99
+ };
100
+
101
+ const response = await this.post<WriteFileResult>('/api/write', data);
102
+
103
+ this.logSuccess('File written', `${path} (${content.length} chars)`);
104
+ return response;
105
+ } catch (error) {
106
+ this.logError('writeFile', error);
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Read content from a file
113
+ * @param path - File path to read from
114
+ * @param sessionId - The session ID for this operation
115
+ * @param options - Optional settings (encoding)
116
+ */
117
+ async readFile(
118
+ path: string,
119
+ sessionId: string,
120
+ options?: { encoding?: string }
121
+ ): Promise<ReadFileResult> {
122
+ try {
123
+ const data = {
124
+ path,
125
+ sessionId,
126
+ encoding: options?.encoding ?? 'utf8',
127
+ };
128
+
129
+ const response = await this.post<ReadFileResult>('/api/read', data);
130
+
131
+ this.logSuccess('File read', `${path} (${response.content.length} chars)`);
132
+ return response;
133
+ } catch (error) {
134
+ this.logError('readFile', error);
135
+ throw error;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Stream a file using Server-Sent Events
141
+ * Returns a ReadableStream of SSE events containing metadata, chunks, and completion
142
+ * @param path - File path to stream
143
+ * @param sessionId - The session ID for this operation
144
+ */
145
+ async readFileStream(
146
+ path: string,
147
+ sessionId: string
148
+ ): Promise<ReadableStream<Uint8Array>> {
149
+ try {
150
+ const data = {
151
+ path,
152
+ sessionId,
153
+ };
154
+
155
+ const response = await this.doFetch('/api/read/stream', {
156
+ method: 'POST',
157
+ headers: {
158
+ 'Content-Type': 'application/json',
159
+ },
160
+ body: JSON.stringify(data),
161
+ });
162
+
163
+ const stream = await this.handleStreamResponse(response);
164
+ this.logSuccess('File stream started', path);
165
+ return stream;
166
+ } catch (error) {
167
+ this.logError('readFileStream', error);
168
+ throw error;
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Delete a file
174
+ * @param path - File path to delete
175
+ * @param sessionId - The session ID for this operation
176
+ */
177
+ async deleteFile(
178
+ path: string,
179
+ sessionId: string
180
+ ): Promise<DeleteFileResult> {
181
+ try {
182
+ const data = { path, sessionId };
183
+
184
+ const response = await this.post<DeleteFileResult>('/api/delete', data);
185
+
186
+ this.logSuccess('File deleted', path);
187
+ return response;
188
+ } catch (error) {
189
+ this.logError('deleteFile', error);
190
+ throw error;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Rename a file
196
+ * @param path - Current file path
197
+ * @param newPath - New file path
198
+ * @param sessionId - The session ID for this operation
199
+ */
200
+ async renameFile(
201
+ path: string,
202
+ newPath: string,
203
+ sessionId: string
204
+ ): Promise<RenameFileResult> {
205
+ try {
206
+ const data = { oldPath: path, newPath, sessionId };
207
+
208
+ const response = await this.post<RenameFileResult>('/api/rename', data);
209
+
210
+ this.logSuccess('File renamed', `${path} -> ${newPath}`);
211
+ return response;
212
+ } catch (error) {
213
+ this.logError('renameFile', error);
214
+ throw error;
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Move a file
220
+ * @param path - Current file path
221
+ * @param newPath - Destination file path
222
+ * @param sessionId - The session ID for this operation
223
+ */
224
+ async moveFile(
225
+ path: string,
226
+ newPath: string,
227
+ sessionId: string
228
+ ): Promise<MoveFileResult> {
229
+ try {
230
+ const data = { sourcePath: path, destinationPath: newPath, sessionId };
231
+
232
+ const response = await this.post<MoveFileResult>('/api/move', data);
233
+
234
+ this.logSuccess('File moved', `${path} -> ${newPath}`);
235
+ return response;
236
+ } catch (error) {
237
+ this.logError('moveFile', error);
238
+ throw error;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * List files in a directory
244
+ * @param path - Directory path to list
245
+ * @param sessionId - The session ID for this operation
246
+ * @param options - Optional settings (recursive, includeHidden)
247
+ */
248
+ async listFiles(
249
+ path: string,
250
+ sessionId: string,
251
+ options?: ListFilesOptions
252
+ ): Promise<ListFilesResult> {
253
+ try {
254
+ const data = {
255
+ path,
256
+ sessionId,
257
+ options: options || {},
258
+ };
259
+
260
+ const response = await this.post<ListFilesResult>('/api/list-files', data);
261
+
262
+ this.logSuccess('Files listed', `${path} (${response.count} files)`);
263
+ return response;
264
+ } catch (error) {
265
+ this.logError('listFiles', error);
266
+ throw error;
267
+ }
268
+ }
269
+ }
@@ -0,0 +1,92 @@
1
+ import type { GitCheckoutResult } from '@repo/shared';
2
+ import { BaseHttpClient } from './base-client';
3
+ import type { HttpClientOptions, SessionRequest } from './types';
4
+
5
+ // Re-export for convenience
6
+ export type { GitCheckoutResult };
7
+
8
+ /**
9
+ * Request interface for Git checkout operations
10
+ */
11
+ export interface GitCheckoutRequest extends SessionRequest {
12
+ repoUrl: string;
13
+ branch?: string;
14
+ targetDir?: string;
15
+ }
16
+
17
+ /**
18
+ * Client for Git repository operations
19
+ */
20
+ export class GitClient extends BaseHttpClient {
21
+
22
+ /**
23
+ * Clone a Git repository
24
+ * @param repoUrl - URL of the Git repository to clone
25
+ * @param sessionId - The session ID for this operation
26
+ * @param options - Optional settings (branch, targetDir)
27
+ */
28
+ async checkout(
29
+ repoUrl: string,
30
+ sessionId: string,
31
+ options?: {
32
+ branch?: string;
33
+ targetDir?: string;
34
+ }
35
+ ): Promise<GitCheckoutResult> {
36
+ try {
37
+ // Determine target directory - use provided path or generate from repo name
38
+ let targetDir = options?.targetDir;
39
+ if (!targetDir) {
40
+ const repoName = this.extractRepoName(repoUrl);
41
+ // Ensure absolute path in /workspace
42
+ targetDir = `/workspace/${repoName}`;
43
+ }
44
+
45
+ const data: GitCheckoutRequest = {
46
+ repoUrl,
47
+ sessionId,
48
+ targetDir,
49
+ };
50
+
51
+ // Only include branch if explicitly specified
52
+ // This allows Git to use the repository's default branch
53
+ if (options?.branch) {
54
+ data.branch = options.branch;
55
+ }
56
+
57
+ const response = await this.post<GitCheckoutResult>(
58
+ '/api/git/checkout',
59
+ data
60
+ );
61
+
62
+ this.logSuccess(
63
+ 'Repository cloned',
64
+ `${repoUrl} (branch: ${response.branch}) -> ${response.targetDir}`
65
+ );
66
+
67
+ return response;
68
+ } catch (error) {
69
+ this.logError('checkout', error);
70
+ throw error;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Extract repository name from URL for default directory name
76
+ */
77
+ private extractRepoName(repoUrl: string): string {
78
+ try {
79
+ const url = new URL(repoUrl);
80
+ const pathParts = url.pathname.split('/');
81
+ const repoName = pathParts[pathParts.length - 1];
82
+
83
+ // Remove .git extension if present
84
+ return repoName.replace(/\.git$/, '');
85
+ } catch {
86
+ // Fallback for invalid URLs
87
+ const parts = repoUrl.split('/');
88
+ const repoName = parts[parts.length - 1];
89
+ return repoName.replace(/\.git$/, '') || 'repo';
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,64 @@
1
+ // Main client exports
2
+
3
+
4
+ // Command client types
5
+ export type {
6
+ ExecuteRequest,
7
+ ExecuteResponse,
8
+ } from './command-client';
9
+
10
+ // Domain-specific clients
11
+ export { CommandClient } from './command-client';
12
+ // File client types
13
+ export type {
14
+ FileOperationRequest,
15
+ MkdirRequest,
16
+ ReadFileRequest,
17
+ WriteFileRequest,
18
+ } from './file-client';
19
+ export { FileClient } from './file-client';
20
+ // Git client types
21
+ export type {
22
+ GitCheckoutRequest,
23
+ GitCheckoutResult,
24
+ } from './git-client';
25
+ export { GitClient } from './git-client';
26
+ export { type ExecutionCallbacks, InterpreterClient } from './interpreter-client';
27
+ // Port client types
28
+ export type {
29
+ ExposePortRequest,
30
+ PortCloseResult,
31
+ PortExposeResult,
32
+ PortListResult,
33
+ UnexposePortRequest,
34
+ } from './port-client';
35
+ export { PortClient } from './port-client';
36
+ // Process client types
37
+ export type {
38
+ ProcessCleanupResult,
39
+ ProcessInfoResult,
40
+ ProcessKillResult,
41
+ ProcessListResult,
42
+ ProcessLogsResult,
43
+ ProcessStartResult,
44
+ StartProcessRequest,
45
+ } from './process-client';
46
+ export { ProcessClient } from './process-client';
47
+ export { SandboxClient } from './sandbox-client';
48
+ // Types and interfaces
49
+ export type {
50
+ BaseApiResponse,
51
+ ContainerStub,
52
+ ErrorResponse,
53
+ HttpClientOptions,
54
+ RequestConfig,
55
+ ResponseHandler,
56
+ SessionRequest,
57
+ } from './types';
58
+ // Utility client types
59
+ export type {
60
+ CommandsResponse,
61
+ PingResponse,
62
+ VersionResponse,
63
+ } from './utility-client';
64
+ export { UtilityClient } from './utility-client';