@cloudflare/sandbox 0.4.5 → 0.4.7
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/.turbo/turbo-build.log +18 -13
- package/CHANGELOG.md +14 -0
- package/Dockerfile +6 -0
- package/dist/chunk-KWOEDJUN.js +7 -0
- package/dist/chunk-KWOEDJUN.js.map +1 -0
- package/dist/{chunk-WK36EMRB.js → chunk-Y52QYTSM.js} +48 -2
- package/dist/chunk-Y52QYTSM.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/interpreter.d.ts +1 -1
- package/dist/request-handler.d.ts +1 -1
- package/dist/request-handler.js +2 -1
- package/dist/{sandbox-B1TT7PZP.d.ts → sandbox-DMlNr93l.d.ts} +10 -0
- package/dist/sandbox.d.ts +1 -1
- package/dist/sandbox.js +2 -1
- package/dist/version.d.ts +8 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +4 -4
- package/src/clients/index.ts +1 -0
- package/src/clients/utility-client.ts +25 -0
- package/src/sandbox.ts +50 -1
- package/src/version.ts +6 -0
- package/tests/utility-client.test.ts +67 -1
- package/tests/version.test.ts +16 -0
- package/dist/chunk-WK36EMRB.js.map +0 -1
package/dist/interpreter.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CreateContextOptions, CodeContext, RunCodeOptions, Execution } from '@repo/shared';
|
|
2
|
-
import { b as Sandbox } from './sandbox-
|
|
2
|
+
import { b as Sandbox } from './sandbox-DMlNr93l.js';
|
|
3
3
|
import 'cloudflare:workers';
|
|
4
4
|
import '@cloudflare/containers';
|
|
5
5
|
|
package/dist/request-handler.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isLocalhostPattern,
|
|
3
3
|
proxyToSandbox
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Y52QYTSM.js";
|
|
5
5
|
import "./chunk-JXZMAU2C.js";
|
|
6
6
|
import "./chunk-Z532A7QC.js";
|
|
7
7
|
import "./chunk-EKSWCBCA.js";
|
|
8
|
+
import "./chunk-KWOEDJUN.js";
|
|
8
9
|
export {
|
|
9
10
|
isLocalhostPattern,
|
|
10
11
|
proxyToSandbox
|
|
@@ -418,6 +418,11 @@ declare class UtilityClient extends BaseHttpClient {
|
|
|
418
418
|
* @param options - Session configuration (id, env, cwd)
|
|
419
419
|
*/
|
|
420
420
|
createSession(options: CreateSessionRequest): Promise<CreateSessionResponse>;
|
|
421
|
+
/**
|
|
422
|
+
* Get the container version
|
|
423
|
+
* Returns the version embedded in the Docker image during build
|
|
424
|
+
*/
|
|
425
|
+
getVersion(): Promise<string>;
|
|
421
426
|
}
|
|
422
427
|
|
|
423
428
|
/**
|
|
@@ -457,6 +462,11 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
457
462
|
*/
|
|
458
463
|
destroy(): Promise<void>;
|
|
459
464
|
onStart(): void;
|
|
465
|
+
/**
|
|
466
|
+
* Check if the container version matches the SDK version
|
|
467
|
+
* Logs a warning if there's a mismatch
|
|
468
|
+
*/
|
|
469
|
+
private checkVersionCompatibility;
|
|
460
470
|
onStop(): void;
|
|
461
471
|
onError(error: unknown): void;
|
|
462
472
|
fetch(request: Request): Promise<Response>;
|
package/dist/sandbox.d.ts
CHANGED
package/dist/sandbox.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Sandbox,
|
|
3
3
|
getSandbox
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Y52QYTSM.js";
|
|
5
5
|
import "./chunk-JXZMAU2C.js";
|
|
6
6
|
import "./chunk-Z532A7QC.js";
|
|
7
7
|
import "./chunk-EKSWCBCA.js";
|
|
8
|
+
import "./chunk-KWOEDJUN.js";
|
|
8
9
|
export {
|
|
9
10
|
Sandbox,
|
|
10
11
|
getSandbox
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK version - automatically synchronized with package.json by Changesets
|
|
3
|
+
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
4
|
+
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
5
|
+
*/
|
|
6
|
+
declare const SDK_VERSION = "0.4.7";
|
|
7
|
+
|
|
8
|
+
export { SDK_VERSION };
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/sandbox",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cloudflare/sandbox-sdk"
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"check": "biome check && npm run typecheck",
|
|
25
25
|
"fix": "biome check --fix && npm run typecheck",
|
|
26
26
|
"typecheck": "tsc --noEmit",
|
|
27
|
-
"docker:local": "cd ../.. && docker build -f packages/sandbox/Dockerfile -t cloudflare/sandbox-test:$npm_package_version .",
|
|
28
|
-
"docker:publish": "cd ../.. && docker buildx build --platform linux/amd64,linux/arm64 -f packages/sandbox/Dockerfile -t cloudflare/sandbox:$npm_package_version --push .",
|
|
29
|
-
"docker:publish:beta": "cd ../.. && docker buildx build --platform linux/amd64,linux/arm64 -f packages/sandbox/Dockerfile -t cloudflare/sandbox:$npm_package_version-beta --push .",
|
|
27
|
+
"docker:local": "cd ../.. && docker build -f packages/sandbox/Dockerfile --build-arg SANDBOX_VERSION=$npm_package_version -t cloudflare/sandbox-test:$npm_package_version .",
|
|
28
|
+
"docker:publish": "cd ../.. && docker buildx build --platform linux/amd64,linux/arm64 -f packages/sandbox/Dockerfile --build-arg SANDBOX_VERSION=$npm_package_version -t cloudflare/sandbox:$npm_package_version --push .",
|
|
29
|
+
"docker:publish:beta": "cd ../.. && docker buildx build --platform linux/amd64,linux/arm64 -f packages/sandbox/Dockerfile --build-arg SANDBOX_VERSION=$npm_package_version -t cloudflare/sandbox:$npm_package_version-beta --push .",
|
|
30
30
|
"test": "vitest run --config vitest.config.ts",
|
|
31
31
|
"test:e2e": "cd ../.. && vitest run --config vitest.e2e.config.ts \"$@\""
|
|
32
32
|
},
|
package/src/clients/index.ts
CHANGED
|
@@ -17,6 +17,13 @@ export interface CommandsResponse extends BaseApiResponse {
|
|
|
17
17
|
count: number;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Response interface for getting container version
|
|
22
|
+
*/
|
|
23
|
+
export interface VersionResponse extends BaseApiResponse {
|
|
24
|
+
version: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
/**
|
|
21
28
|
* Request interface for creating sessions
|
|
22
29
|
*/
|
|
@@ -91,4 +98,22 @@ export class UtilityClient extends BaseHttpClient {
|
|
|
91
98
|
throw error;
|
|
92
99
|
}
|
|
93
100
|
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get the container version
|
|
104
|
+
* Returns the version embedded in the Docker image during build
|
|
105
|
+
*/
|
|
106
|
+
async getVersion(): Promise<string> {
|
|
107
|
+
try {
|
|
108
|
+
const response = await this.get<VersionResponse>('/api/version');
|
|
109
|
+
|
|
110
|
+
this.logSuccess('Version retrieved', response.version);
|
|
111
|
+
return response.version;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
// If version endpoint doesn't exist (old container), return 'unknown'
|
|
114
|
+
// This allows for backward compatibility
|
|
115
|
+
this.logger.debug('Failed to get container version (may be old container)', { error });
|
|
116
|
+
return 'unknown';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
94
119
|
}
|
package/src/sandbox.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
validatePort
|
|
30
30
|
} from "./security";
|
|
31
31
|
import { parseSSEStream } from "./sse-parser";
|
|
32
|
+
import { SDK_VERSION } from "./version";
|
|
32
33
|
|
|
33
34
|
export function getSandbox(
|
|
34
35
|
ns: DurableObjectNamespace<Sandbox>,
|
|
@@ -161,6 +162,54 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
|
|
|
161
162
|
|
|
162
163
|
override onStart() {
|
|
163
164
|
this.logger.debug('Sandbox started');
|
|
165
|
+
|
|
166
|
+
// Check version compatibility asynchronously (don't block startup)
|
|
167
|
+
this.checkVersionCompatibility().catch(error => {
|
|
168
|
+
this.logger.error('Version compatibility check failed', error instanceof Error ? error : new Error(String(error)));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Check if the container version matches the SDK version
|
|
174
|
+
* Logs a warning if there's a mismatch
|
|
175
|
+
*/
|
|
176
|
+
private async checkVersionCompatibility(): Promise<void> {
|
|
177
|
+
try {
|
|
178
|
+
// Get the SDK version (imported from version.ts)
|
|
179
|
+
const sdkVersion = SDK_VERSION;
|
|
180
|
+
|
|
181
|
+
// Get container version
|
|
182
|
+
const containerVersion = await this.client.utils.getVersion();
|
|
183
|
+
|
|
184
|
+
// If container version is unknown, it's likely an old container without the endpoint
|
|
185
|
+
if (containerVersion === 'unknown') {
|
|
186
|
+
this.logger.warn(
|
|
187
|
+
'Container version check: Container version could not be determined. ' +
|
|
188
|
+
'This may indicate an outdated container image. ' +
|
|
189
|
+
'Please update your container to match SDK version ' + sdkVersion
|
|
190
|
+
);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check if versions match
|
|
195
|
+
if (containerVersion !== sdkVersion) {
|
|
196
|
+
const message =
|
|
197
|
+
`Version mismatch detected! SDK version (${sdkVersion}) does not match ` +
|
|
198
|
+
`container version (${containerVersion}). This may cause compatibility issues. ` +
|
|
199
|
+
`Please update your container image to version ${sdkVersion}`;
|
|
200
|
+
|
|
201
|
+
// Log warning - we can't reliably detect dev vs prod environment in Durable Objects
|
|
202
|
+
// so we always use warning level as requested by the user
|
|
203
|
+
this.logger.warn(message);
|
|
204
|
+
} else {
|
|
205
|
+
this.logger.debug('Version check passed', { sdkVersion, containerVersion });
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
// Don't fail the sandbox initialization if version check fails
|
|
209
|
+
this.logger.debug('Version compatibility check encountered an error', {
|
|
210
|
+
error: error instanceof Error ? error.message : String(error)
|
|
211
|
+
});
|
|
212
|
+
}
|
|
164
213
|
}
|
|
165
214
|
|
|
166
215
|
override onStop() {
|
|
@@ -235,7 +284,7 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
|
|
|
235
284
|
this.logger.debug('Default session initialized', { sessionId });
|
|
236
285
|
} catch (error: any) {
|
|
237
286
|
// If session already exists (e.g., after hot reload), reuse it
|
|
238
|
-
if (error?.message?.includes('already exists')
|
|
287
|
+
if (error?.message?.includes('already exists')) {
|
|
239
288
|
this.logger.debug('Reusing existing session after reload', { sessionId });
|
|
240
289
|
this.defaultSession = sessionId;
|
|
241
290
|
// Persist to storage in case it wasn't saved before
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK version - automatically synchronized with package.json by Changesets
|
|
3
|
+
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
4
|
+
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
5
|
+
*/
|
|
6
|
+
export const SDK_VERSION = '0.4.7';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import type {
|
|
3
3
|
CommandsResponse,
|
|
4
|
-
PingResponse
|
|
4
|
+
PingResponse,
|
|
5
|
+
VersionResponse
|
|
5
6
|
} from '../src/clients';
|
|
6
7
|
import { UtilityClient } from '../src/clients/utility-client';
|
|
7
8
|
import {
|
|
@@ -25,6 +26,13 @@ const mockCommandsResponse = (commands: string[], overrides: Partial<CommandsRes
|
|
|
25
26
|
...overrides
|
|
26
27
|
});
|
|
27
28
|
|
|
29
|
+
const mockVersionResponse = (version: string = '0.4.5', overrides: Partial<VersionResponse> = {}): VersionResponse => ({
|
|
30
|
+
success: true,
|
|
31
|
+
version,
|
|
32
|
+
timestamp: '2023-01-01T00:00:00Z',
|
|
33
|
+
...overrides
|
|
34
|
+
});
|
|
35
|
+
|
|
28
36
|
describe('UtilityClient', () => {
|
|
29
37
|
let client: UtilityClient;
|
|
30
38
|
let mockFetch: ReturnType<typeof vi.fn>;
|
|
@@ -249,6 +257,64 @@ describe('UtilityClient', () => {
|
|
|
249
257
|
});
|
|
250
258
|
});
|
|
251
259
|
|
|
260
|
+
describe('version checking', () => {
|
|
261
|
+
it('should get container version successfully', async () => {
|
|
262
|
+
mockFetch.mockResolvedValue(new Response(
|
|
263
|
+
JSON.stringify(mockVersionResponse('0.4.5')),
|
|
264
|
+
{ status: 200 }
|
|
265
|
+
));
|
|
266
|
+
|
|
267
|
+
const result = await client.getVersion();
|
|
268
|
+
|
|
269
|
+
expect(result).toBe('0.4.5');
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should handle different version formats', async () => {
|
|
273
|
+
const versions = ['1.0.0', '2.5.3-beta', '0.0.1', '10.20.30'];
|
|
274
|
+
|
|
275
|
+
for (const version of versions) {
|
|
276
|
+
mockFetch.mockResolvedValueOnce(new Response(
|
|
277
|
+
JSON.stringify(mockVersionResponse(version)),
|
|
278
|
+
{ status: 200 }
|
|
279
|
+
));
|
|
280
|
+
|
|
281
|
+
const result = await client.getVersion();
|
|
282
|
+
expect(result).toBe(version);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should return "unknown" when version endpoint does not exist (backward compatibility)', async () => {
|
|
287
|
+
// Simulate 404 or other error for old containers
|
|
288
|
+
mockFetch.mockResolvedValue(new Response(
|
|
289
|
+
JSON.stringify({ error: 'Not Found' }),
|
|
290
|
+
{ status: 404 }
|
|
291
|
+
));
|
|
292
|
+
|
|
293
|
+
const result = await client.getVersion();
|
|
294
|
+
|
|
295
|
+
expect(result).toBe('unknown');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should return "unknown" on network failure (backward compatibility)', async () => {
|
|
299
|
+
mockFetch.mockRejectedValue(new Error('Network connection failed'));
|
|
300
|
+
|
|
301
|
+
const result = await client.getVersion();
|
|
302
|
+
|
|
303
|
+
expect(result).toBe('unknown');
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('should handle version response with unknown value', async () => {
|
|
307
|
+
mockFetch.mockResolvedValue(new Response(
|
|
308
|
+
JSON.stringify(mockVersionResponse('unknown')),
|
|
309
|
+
{ status: 200 }
|
|
310
|
+
));
|
|
311
|
+
|
|
312
|
+
const result = await client.getVersion();
|
|
313
|
+
|
|
314
|
+
expect(result).toBe('unknown');
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
252
318
|
describe('constructor options', () => {
|
|
253
319
|
it('should initialize with minimal options', () => {
|
|
254
320
|
const minimalClient = new UtilityClient();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import packageJson from '../package.json';
|
|
3
|
+
import { SDK_VERSION } from '../src/version';
|
|
4
|
+
|
|
5
|
+
describe('Version Sync', () => {
|
|
6
|
+
test('SDK_VERSION matches package.json version', () => {
|
|
7
|
+
// Verify versions match
|
|
8
|
+
expect(SDK_VERSION).toBe(packageJson.version);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('SDK_VERSION is a valid semver version', () => {
|
|
12
|
+
// Check if version matches semver pattern (major.minor.patch)
|
|
13
|
+
const semverPattern = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
14
|
+
expect(SDK_VERSION).toMatch(semverPattern);
|
|
15
|
+
});
|
|
16
|
+
});
|