@cloudflare/sandbox 0.4.12 → 0.4.14

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 (79) hide show
  1. package/.turbo/turbo-build.log +13 -47
  2. package/CHANGELOG.md +38 -16
  3. package/Dockerfile +15 -9
  4. package/README.md +0 -1
  5. package/dist/index.d.ts +1889 -9
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3144 -65
  8. package/dist/index.js.map +1 -1
  9. package/package.json +5 -5
  10. package/src/clients/base-client.ts +39 -24
  11. package/src/clients/command-client.ts +8 -8
  12. package/src/clients/file-client.ts +31 -26
  13. package/src/clients/git-client.ts +3 -4
  14. package/src/clients/index.ts +12 -16
  15. package/src/clients/interpreter-client.ts +51 -47
  16. package/src/clients/port-client.ts +10 -10
  17. package/src/clients/process-client.ts +11 -8
  18. package/src/clients/sandbox-client.ts +2 -4
  19. package/src/clients/types.ts +6 -2
  20. package/src/clients/utility-client.ts +10 -6
  21. package/src/errors/adapter.ts +90 -32
  22. package/src/errors/classes.ts +189 -64
  23. package/src/errors/index.ts +9 -5
  24. package/src/file-stream.ts +11 -6
  25. package/src/index.ts +22 -15
  26. package/src/interpreter.ts +50 -41
  27. package/src/request-handler.ts +24 -21
  28. package/src/sandbox.ts +339 -149
  29. package/src/security.ts +21 -6
  30. package/src/sse-parser.ts +4 -3
  31. package/src/version.ts +1 -1
  32. package/tests/base-client.test.ts +116 -80
  33. package/tests/command-client.test.ts +149 -112
  34. package/tests/file-client.test.ts +309 -197
  35. package/tests/file-stream.test.ts +24 -20
  36. package/tests/get-sandbox.test.ts +10 -10
  37. package/tests/git-client.test.ts +188 -101
  38. package/tests/port-client.test.ts +100 -108
  39. package/tests/process-client.test.ts +204 -179
  40. package/tests/request-handler.test.ts +117 -65
  41. package/tests/sandbox.test.ts +219 -67
  42. package/tests/sse-parser.test.ts +17 -16
  43. package/tests/utility-client.test.ts +79 -72
  44. package/tsdown.config.ts +12 -0
  45. package/vitest.config.ts +6 -6
  46. package/dist/chunk-BFVUNTP4.js +0 -104
  47. package/dist/chunk-BFVUNTP4.js.map +0 -1
  48. package/dist/chunk-EKSWCBCA.js +0 -86
  49. package/dist/chunk-EKSWCBCA.js.map +0 -1
  50. package/dist/chunk-JXZMAU2C.js +0 -559
  51. package/dist/chunk-JXZMAU2C.js.map +0 -1
  52. package/dist/chunk-UJ3TV4M6.js +0 -7
  53. package/dist/chunk-UJ3TV4M6.js.map +0 -1
  54. package/dist/chunk-YE265ASX.js +0 -2484
  55. package/dist/chunk-YE265ASX.js.map +0 -1
  56. package/dist/chunk-Z532A7QC.js +0 -78
  57. package/dist/chunk-Z532A7QC.js.map +0 -1
  58. package/dist/file-stream.d.ts +0 -43
  59. package/dist/file-stream.js +0 -9
  60. package/dist/file-stream.js.map +0 -1
  61. package/dist/interpreter.d.ts +0 -33
  62. package/dist/interpreter.js +0 -8
  63. package/dist/interpreter.js.map +0 -1
  64. package/dist/request-handler.d.ts +0 -18
  65. package/dist/request-handler.js +0 -13
  66. package/dist/request-handler.js.map +0 -1
  67. package/dist/sandbox-CLZWpfGc.d.ts +0 -613
  68. package/dist/sandbox.d.ts +0 -4
  69. package/dist/sandbox.js +0 -13
  70. package/dist/sandbox.js.map +0 -1
  71. package/dist/security.d.ts +0 -31
  72. package/dist/security.js +0 -13
  73. package/dist/security.js.map +0 -1
  74. package/dist/sse-parser.d.ts +0 -28
  75. package/dist/sse-parser.js +0 -11
  76. package/dist/sse-parser.js.map +0 -1
  77. package/dist/version.d.ts +0 -8
  78. package/dist/version.js +0 -7
  79. package/dist/version.js.map +0 -1
@@ -23,7 +23,7 @@ describe('File Streaming Utilities', () => {
23
23
  'data: {"type":"metadata","mimeType":"text/plain","size":11,"isBinary":false,"encoding":"utf-8"}\n\n',
24
24
  'data: {"type":"chunk","data":"Hello"}\n\n',
25
25
  'data: {"type":"chunk","data":" World"}\n\n',
26
- 'data: {"type":"complete","bytesRead":11}\n\n',
26
+ 'data: {"type":"complete","bytesRead":11}\n\n'
27
27
  ]);
28
28
 
29
29
  const chunks: string[] = [];
@@ -44,7 +44,7 @@ describe('File Streaming Utilities', () => {
44
44
  mimeType: 'text/plain',
45
45
  size: 11,
46
46
  isBinary: false,
47
- encoding: 'utf-8',
47
+ encoding: 'utf-8'
48
48
  });
49
49
  });
50
50
 
@@ -53,7 +53,7 @@ describe('File Streaming Utilities', () => {
53
53
  const stream = createMockSSEStream([
54
54
  'data: {"type":"metadata","mimeType":"image/png","size":4,"isBinary":true,"encoding":"base64"}\n\n',
55
55
  'data: {"type":"chunk","data":"dGVzdA=="}\n\n',
56
- 'data: {"type":"complete","bytesRead":4}\n\n',
56
+ 'data: {"type":"complete","bytesRead":4}\n\n'
57
57
  ]);
58
58
 
59
59
  const chunks: (string | Uint8Array)[] = [];
@@ -101,7 +101,7 @@ describe('File Streaming Utilities', () => {
101
101
  it('should handle empty files', async () => {
102
102
  const stream = createMockSSEStream([
103
103
  'data: {"type":"metadata","mimeType":"text/plain","size":0,"isBinary":false,"encoding":"utf-8"}\n\n',
104
- 'data: {"type":"complete","bytesRead":0}\n\n',
104
+ 'data: {"type":"complete","bytesRead":0}\n\n'
105
105
  ]);
106
106
 
107
107
  const chunks: string[] = [];
@@ -123,7 +123,7 @@ describe('File Streaming Utilities', () => {
123
123
  const stream = createMockSSEStream([
124
124
  'data: {"type":"metadata","mimeType":"text/plain","size":100,"isBinary":false,"encoding":"utf-8"}\n\n',
125
125
  'data: {"type":"chunk","data":"Hello"}\n\n',
126
- 'data: {"type":"error","error":"Read error: Permission denied"}\n\n',
126
+ 'data: {"type":"error","error":"Read error: Permission denied"}\n\n'
127
127
  ]);
128
128
 
129
129
  const generator = streamFile(stream);
@@ -136,7 +136,9 @@ describe('File Streaming Utilities', () => {
136
136
  // Should have thrown
137
137
  expect(true).toBe(false);
138
138
  } catch (error) {
139
- expect((error as Error).message).toContain('Read error: Permission denied');
139
+ expect((error as Error).message).toContain(
140
+ 'Read error: Permission denied'
141
+ );
140
142
  }
141
143
  });
142
144
  });
@@ -147,7 +149,7 @@ describe('File Streaming Utilities', () => {
147
149
  'data: {"type":"metadata","mimeType":"text/plain","size":11,"isBinary":false,"encoding":"utf-8"}\n\n',
148
150
  'data: {"type":"chunk","data":"Hello"}\n\n',
149
151
  'data: {"type":"chunk","data":" World"}\n\n',
150
- 'data: {"type":"complete","bytesRead":11}\n\n',
152
+ 'data: {"type":"complete","bytesRead":11}\n\n'
151
153
  ]);
152
154
 
153
155
  const result = await collectFile(stream);
@@ -157,7 +159,7 @@ describe('File Streaming Utilities', () => {
157
159
  mimeType: 'text/plain',
158
160
  size: 11,
159
161
  isBinary: false,
160
- encoding: 'utf-8',
162
+ encoding: 'utf-8'
161
163
  });
162
164
  });
163
165
 
@@ -166,7 +168,7 @@ describe('File Streaming Utilities', () => {
166
168
  const stream = createMockSSEStream([
167
169
  'data: {"type":"metadata","mimeType":"image/png","size":4,"isBinary":true,"encoding":"base64"}\n\n',
168
170
  'data: {"type":"chunk","data":"dGVzdA=="}\n\n',
169
- 'data: {"type":"complete","bytesRead":4}\n\n',
171
+ 'data: {"type":"complete","bytesRead":4}\n\n'
170
172
  ]);
171
173
 
172
174
  const result = await collectFile(stream);
@@ -182,7 +184,7 @@ describe('File Streaming Utilities', () => {
182
184
  it('should handle empty files', async () => {
183
185
  const stream = createMockSSEStream([
184
186
  'data: {"type":"metadata","mimeType":"text/plain","size":0,"isBinary":false,"encoding":"utf-8"}\n\n',
185
- 'data: {"type":"complete","bytesRead":0}\n\n',
187
+ 'data: {"type":"complete","bytesRead":0}\n\n'
186
188
  ]);
187
189
 
188
190
  const result = await collectFile(stream);
@@ -195,7 +197,7 @@ describe('File Streaming Utilities', () => {
195
197
  const stream = createMockSSEStream([
196
198
  'data: {"type":"metadata","mimeType":"text/plain","size":100,"isBinary":false,"encoding":"utf-8"}\n\n',
197
199
  'data: {"type":"chunk","data":"Hello"}\n\n',
198
- 'data: {"type":"error","error":"File not found"}\n\n',
200
+ 'data: {"type":"error","error":"File not found"}\n\n'
199
201
  ]);
200
202
 
201
203
  await expect(collectFile(stream)).rejects.toThrow('File not found');
@@ -205,7 +207,7 @@ describe('File Streaming Utilities', () => {
205
207
  // Create a stream with many chunks
206
208
  const chunkCount = 100;
207
209
  const events = [
208
- 'data: {"type":"metadata","mimeType":"text/plain","size":500,"isBinary":false,"encoding":"utf-8"}\n\n',
210
+ 'data: {"type":"metadata","mimeType":"text/plain","size":500,"isBinary":false,"encoding":"utf-8"}\n\n'
209
211
  ];
210
212
 
211
213
  for (let i = 0; i < chunkCount; i++) {
@@ -227,7 +229,7 @@ describe('File Streaming Utilities', () => {
227
229
  // Create a stream with many base64 chunks
228
230
  const chunkCount = 100;
229
231
  const events = [
230
- 'data: {"type":"metadata","mimeType":"application/octet-stream","size":400,"isBinary":true,"encoding":"base64"}\n\n',
232
+ 'data: {"type":"metadata","mimeType":"application/octet-stream","size":400,"isBinary":true,"encoding":"base64"}\n\n'
231
233
  ];
232
234
 
233
235
  for (let i = 0; i < chunkCount; i++) {
@@ -250,7 +252,7 @@ describe('File Streaming Utilities', () => {
250
252
  it('should handle streams with no metadata event', async () => {
251
253
  const stream = createMockSSEStream([
252
254
  'data: {"type":"chunk","data":"Hello"}\n\n',
253
- 'data: {"type":"complete","bytesRead":5}\n\n',
255
+ 'data: {"type":"complete","bytesRead":5}\n\n'
254
256
  ]);
255
257
 
256
258
  // Without metadata, we don't know if it's binary or text
@@ -265,7 +267,9 @@ describe('File Streaming Utilities', () => {
265
267
  // Should have thrown
266
268
  expect(true).toBe(false);
267
269
  } catch (error) {
268
- expect((error as Error).message).toContain('Received chunk before metadata');
270
+ expect((error as Error).message).toContain(
271
+ 'Received chunk before metadata'
272
+ );
269
273
  }
270
274
  });
271
275
 
@@ -273,7 +277,7 @@ describe('File Streaming Utilities', () => {
273
277
  const stream = createMockSSEStream([
274
278
  'data: {"type":"metadata","mimeType":"text/plain","size":5,"isBinary":false,"encoding":"utf-8"}\n\n',
275
279
  'data: {invalid json\n\n',
276
- 'data: {"type":"complete","bytesRead":5}\n\n',
280
+ 'data: {"type":"complete","bytesRead":5}\n\n'
277
281
  ]);
278
282
 
279
283
  // Malformed JSON is logged but doesn't break the stream
@@ -285,16 +289,16 @@ describe('File Streaming Utilities', () => {
285
289
  it('should handle base64 padding correctly', async () => {
286
290
  // Test various base64 strings with different padding
287
291
  const testCases = [
288
- { input: 'YQ==', expected: 'a' }, // 1 byte, 2 padding
289
- { input: 'YWI=', expected: 'ab' }, // 2 bytes, 1 padding
290
- { input: 'YWJj', expected: 'abc' }, // 3 bytes, no padding
292
+ { input: 'YQ==', expected: 'a' }, // 1 byte, 2 padding
293
+ { input: 'YWI=', expected: 'ab' }, // 2 bytes, 1 padding
294
+ { input: 'YWJj', expected: 'abc' } // 3 bytes, no padding
291
295
  ];
292
296
 
293
297
  for (const testCase of testCases) {
294
298
  const stream = createMockSSEStream([
295
299
  `data: {"type":"metadata","mimeType":"application/octet-stream","size":${testCase.expected.length},"isBinary":true,"encoding":"base64"}\n\n`,
296
300
  `data: {"type":"chunk","data":"${testCase.input}"}\n\n`,
297
- `data: {"type":"complete","bytesRead":${testCase.expected.length}}\n\n`,
301
+ `data: {"type":"complete","bytesRead":${testCase.expected.length}}\n\n`
298
302
  ]);
299
303
 
300
304
  const result = await collectFile(stream);
@@ -12,7 +12,7 @@ vi.mock('@cloudflare/containers', () => ({
12
12
  this.env = env;
13
13
  }
14
14
  },
15
- getContainer: vi.fn(),
15
+ getContainer: vi.fn()
16
16
  }));
17
17
 
18
18
  describe('getSandbox', () => {
@@ -30,7 +30,7 @@ describe('getSandbox', () => {
30
30
  setSleepAfter: vi.fn((value: string | number) => {
31
31
  mockStub.sleepAfter = value;
32
32
  }),
33
- setKeepAlive: vi.fn(),
33
+ setKeepAlive: vi.fn()
34
34
  };
35
35
 
36
36
  // Mock getContainer to return our stub
@@ -50,7 +50,7 @@ describe('getSandbox', () => {
50
50
  it('should apply sleepAfter option when provided as string', () => {
51
51
  const mockNamespace = {} as any;
52
52
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
53
- sleepAfter: '5m',
53
+ sleepAfter: '5m'
54
54
  });
55
55
 
56
56
  expect(sandbox.sleepAfter).toBe('5m');
@@ -59,7 +59,7 @@ describe('getSandbox', () => {
59
59
  it('should apply sleepAfter option when provided as number', () => {
60
60
  const mockNamespace = {} as any;
61
61
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
62
- sleepAfter: 300, // 5 minutes in seconds
62
+ sleepAfter: 300 // 5 minutes in seconds
63
63
  });
64
64
 
65
65
  expect(sandbox.sleepAfter).toBe(300);
@@ -68,7 +68,7 @@ describe('getSandbox', () => {
68
68
  it('should apply baseUrl option when provided', () => {
69
69
  const mockNamespace = {} as any;
70
70
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
71
- baseUrl: 'https://example.com',
71
+ baseUrl: 'https://example.com'
72
72
  });
73
73
 
74
74
  expect(sandbox.setBaseUrl).toHaveBeenCalledWith('https://example.com');
@@ -78,7 +78,7 @@ describe('getSandbox', () => {
78
78
  const mockNamespace = {} as any;
79
79
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
80
80
  sleepAfter: '10m',
81
- baseUrl: 'https://example.com',
81
+ baseUrl: 'https://example.com'
82
82
  });
83
83
 
84
84
  expect(sandbox.sleepAfter).toBe('10m');
@@ -102,7 +102,7 @@ describe('getSandbox', () => {
102
102
  mockStub.sleepAfter = '3m';
103
103
 
104
104
  const sandbox = getSandbox(mockNamespace, `test-sandbox-${timeString}`, {
105
- sleepAfter: timeString,
105
+ sleepAfter: timeString
106
106
  });
107
107
 
108
108
  expect(sandbox.sleepAfter).toBe(timeString);
@@ -112,7 +112,7 @@ describe('getSandbox', () => {
112
112
  it('should apply keepAlive option when provided as true', () => {
113
113
  const mockNamespace = {} as any;
114
114
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
115
- keepAlive: true,
115
+ keepAlive: true
116
116
  });
117
117
 
118
118
  expect(sandbox.setKeepAlive).toHaveBeenCalledWith(true);
@@ -121,7 +121,7 @@ describe('getSandbox', () => {
121
121
  it('should apply keepAlive option when provided as false', () => {
122
122
  const mockNamespace = {} as any;
123
123
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
124
- keepAlive: false,
124
+ keepAlive: false
125
125
  });
126
126
 
127
127
  expect(sandbox.setKeepAlive).toHaveBeenCalledWith(false);
@@ -139,7 +139,7 @@ describe('getSandbox', () => {
139
139
  const sandbox = getSandbox(mockNamespace, 'test-sandbox', {
140
140
  sleepAfter: '5m',
141
141
  baseUrl: 'https://example.com',
142
- keepAlive: true,
142
+ keepAlive: true
143
143
  });
144
144
 
145
145
  expect(sandbox.sleepAfter).toBe('5m');