@brimble/sandbox 0.1.0 → 0.1.1

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 (48) hide show
  1. package/dist/package.json +9 -2
  2. package/package.json +7 -3
  3. package/CODEX.md +0 -188
  4. package/PLAN.md +0 -364
  5. package/src/client.ts +0 -61
  6. package/src/constants.ts +0 -17
  7. package/src/enums/code-language.ts +0 -4
  8. package/src/enums/destroy-reason.ts +0 -8
  9. package/src/enums/destroy-timeout.ts +0 -8
  10. package/src/enums/index.ts +0 -7
  11. package/src/enums/sandbox-status.ts +0 -9
  12. package/src/enums/snapshot-mode.ts +0 -4
  13. package/src/enums/snapshot-status.ts +0 -5
  14. package/src/enums/volume-type.ts +0 -3
  15. package/src/errors/index.ts +0 -2
  16. package/src/errors/sandbox-api-error.ts +0 -54
  17. package/src/index.ts +0 -71
  18. package/src/resources/exec.ts +0 -56
  19. package/src/resources/files.ts +0 -46
  20. package/src/resources/index.ts +0 -8
  21. package/src/resources/path.ts +0 -16
  22. package/src/resources/sandbox-handle.ts +0 -215
  23. package/src/resources/sandboxes.ts +0 -297
  24. package/src/resources/scoped-sandbox.ts +0 -65
  25. package/src/resources/snapshots.ts +0 -104
  26. package/src/resources/stats.ts +0 -30
  27. package/src/resources/volumes.ts +0 -95
  28. package/src/transport/auth.ts +0 -4
  29. package/src/transport/http.ts +0 -501
  30. package/src/transport/pagination.ts +0 -10
  31. package/src/types/exec.ts +0 -42
  32. package/src/types/files.ts +0 -1
  33. package/src/types/index.ts +0 -23
  34. package/src/types/pagination.ts +0 -16
  35. package/src/types/region.ts +0 -19
  36. package/src/types/sandbox.ts +0 -103
  37. package/src/types/snapshot.ts +0 -17
  38. package/src/types/stats.ts +0 -35
  39. package/src/types/template.ts +0 -5
  40. package/src/types/volume.ts +0 -26
  41. package/test/integration/sandbox.integration.test.ts +0 -269
  42. package/test/unit/client.test.ts +0 -87
  43. package/test/unit/sandboxes.test.ts +0 -69
  44. package/test/unit/transport.test.ts +0 -126
  45. package/test/unit/volumes.test.ts +0 -122
  46. package/tsconfig.json +0 -16
  47. package/vitest.config.ts +0 -12
  48. package/vitest.integration.config.ts +0 -15
@@ -1,126 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest';
2
-
3
- import { SDK_PACKAGE_VERSION } from '../../src/constants';
4
- import { AuthError, NotFoundError, RateLimitError, ValidationError } from '../../src/errors';
5
- import { HttpTransport } from '../../src/transport/http';
6
-
7
- function createJsonResponse(payload: unknown, status = 200, headers: Record<string, string> = {}): Response {
8
- return new Response(JSON.stringify(payload), {
9
- status,
10
- headers: {
11
- 'content-type': 'application/json',
12
- ...headers,
13
- },
14
- });
15
- }
16
-
17
- describe('HttpTransport', () => {
18
- test('unwraps JSON response envelope data', async () => {
19
- const fetchImpl = vi.fn(async () => createJsonResponse({ message: 'ok', data: { id: 'sandbox-1' } })) as typeof fetch;
20
-
21
- const transport = new HttpTransport({
22
- baseUrl: 'https://sandbox.brimble.io',
23
- apiKey: 'test-key',
24
- fetchImpl,
25
- });
26
-
27
- const result = await transport.requestJson<{ id: string }>({
28
- endpoint: '/sandboxes/sandbox-1',
29
- method: 'GET',
30
- });
31
-
32
- expect(result).toEqual({ id: 'sandbox-1' });
33
- });
34
-
35
- test('returns undefined for HTTP 204', async () => {
36
- const fetchImpl = vi.fn(async () => new Response(null, { status: 204 })) as typeof fetch;
37
-
38
- const transport = new HttpTransport({
39
- baseUrl: 'https://sandbox.brimble.io',
40
- apiKey: 'test-key',
41
- fetchImpl,
42
- });
43
-
44
- const result = await transport.requestJson({
45
- endpoint: '/sandboxes/sandbox-1',
46
- method: 'DELETE',
47
- });
48
-
49
- expect(result).toBeUndefined();
50
- });
51
-
52
- test('sends SDK tracing and auth headers', async () => {
53
- let seenAuthHeader: string | null = null;
54
- let seenSourceHeader: string | null = null;
55
- let seenSourceVersionHeader: string | null = null;
56
-
57
- const fetchImpl = vi.fn(async (_url: URL | RequestInfo, init?: RequestInit) => {
58
- const headers = new Headers(init?.headers);
59
- seenAuthHeader = headers.get('x-brimble-key');
60
- seenSourceHeader = headers.get('source');
61
- seenSourceVersionHeader = headers.get('source-version');
62
- return createJsonResponse({ message: 'ok', data: { regions: [] } });
63
- }) as typeof fetch;
64
-
65
- const transport = new HttpTransport({
66
- baseUrl: 'https://sandbox.brimble.io',
67
- apiKey: 'header-test-key',
68
- fetchImpl,
69
- });
70
-
71
- await transport.requestJson({ endpoint: '/sandboxes/regions', method: 'GET' });
72
-
73
- expect(seenAuthHeader).toBe('header-test-key');
74
- expect(seenSourceHeader).toBe('sdk-package');
75
- expect(seenSourceVersionHeader).toBe(SDK_PACKAGE_VERSION);
76
- });
77
-
78
- test('maps auth and validation errors to typed errors', async () => {
79
- const authFetch = vi.fn(async () => createJsonResponse({ message: 'forbidden' }, 403)) as typeof fetch;
80
- const validationFetch = vi.fn(async () => createJsonResponse({ message: 'bad input' }, 400)) as typeof fetch;
81
-
82
- const authTransport = new HttpTransport({
83
- baseUrl: 'https://sandbox.brimble.io',
84
- apiKey: 'test-key',
85
- fetchImpl: authFetch,
86
- });
87
-
88
- const validationTransport = new HttpTransport({
89
- baseUrl: 'https://sandbox.brimble.io',
90
- apiKey: 'test-key',
91
- fetchImpl: validationFetch,
92
- });
93
-
94
- await expect(authTransport.requestJson({ endpoint: '/sandboxes', method: 'GET' })).rejects.toBeInstanceOf(AuthError);
95
- await expect(validationTransport.requestJson({ endpoint: '/volumes', method: 'POST' })).rejects.toBeInstanceOf(ValidationError);
96
- });
97
-
98
- test('maps not-found and rate-limit responses to typed errors', async () => {
99
- const notFoundFetch = vi.fn(async () => createJsonResponse({ message: 'missing' }, 404)) as typeof fetch;
100
- const rateLimitFetch = vi.fn(async () => createJsonResponse({ message: 'slow down' }, 429, { 'retry-after': '3' })) as typeof fetch;
101
-
102
- const notFoundTransport = new HttpTransport({
103
- baseUrl: 'https://sandbox.brimble.io',
104
- apiKey: 'test-key',
105
- fetchImpl: notFoundFetch,
106
- });
107
-
108
- const rateLimitTransport = new HttpTransport({
109
- baseUrl: 'https://sandbox.brimble.io',
110
- apiKey: 'test-key',
111
- fetchImpl: rateLimitFetch,
112
- });
113
-
114
- const notFoundError = await notFoundTransport
115
- .requestJson({ endpoint: '/sandboxes/missing', method: 'GET' })
116
- .catch((error) => error);
117
- const rateLimitError = await rateLimitTransport
118
- .requestJson({ endpoint: '/sandboxes', method: 'GET' })
119
- .catch((error) => error);
120
-
121
- expect(notFoundError).toBeInstanceOf(NotFoundError);
122
- expect(notFoundError.endpoint).toBe('GET /sandboxes/missing');
123
- expect(rateLimitError).toBeInstanceOf(RateLimitError);
124
- expect(rateLimitError.retryAfterSeconds).toBe(3);
125
- });
126
- });
@@ -1,122 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest';
2
-
3
- import { MIN_VOLUME_SIZE_GB } from '../../src/constants';
4
- import { VolumeType } from '../../src/enums';
5
- import { VolumesResource } from '../../src/resources/volumes';
6
- import { HttpTransport } from '../../src/transport/http';
7
- import type { Volume } from '../../src/types';
8
-
9
- const volumeFixture: Volume = {
10
- id: 'vol-1',
11
- name: 'workspace',
12
- type: VolumeType.Sandbox,
13
- team: null,
14
- csi_volume_id: null,
15
- size: 20,
16
- region: {
17
- id: 'region-1',
18
- name: 'US East',
19
- country: 'United States',
20
- continent: 'North America',
21
- provider: 'aws',
22
- is_paid: false,
23
- },
24
- mount_path: null,
25
- attached_sandbox_id: null,
26
- attached_project_id: null,
27
- last_attached_at: null,
28
- created_at: null,
29
- updated_at: null,
30
- };
31
-
32
- describe('VolumesResource', () => {
33
- test('rejects non-sandbox volume types', () => {
34
- const fetchImpl = vi.fn(async () => {
35
- throw new Error('fetch should not be called for validation failures');
36
- }) as typeof fetch;
37
-
38
- const transport = new HttpTransport({
39
- baseUrl: 'https://sandbox.brimble.io',
40
- apiKey: 'test-key',
41
- fetchImpl,
42
- });
43
-
44
- const volumes = new VolumesResource(transport);
45
-
46
- expect(() =>
47
- volumes.create({
48
- name: 'invalid-volume',
49
- sizeGB: 20,
50
- region: 'region-1',
51
- type: 'database' as unknown as VolumeType,
52
- }),
53
- ).toThrow('Only volume type "sandbox" is supported by this package.');
54
- });
55
-
56
- test('rejects volume sizes below minimum', () => {
57
- const fetchImpl = vi.fn(async () => {
58
- throw new Error('fetch should not be called for validation failures');
59
- }) as typeof fetch;
60
-
61
- const transport = new HttpTransport({
62
- baseUrl: 'https://sandbox.brimble.io',
63
- apiKey: 'test-key',
64
- fetchImpl,
65
- });
66
-
67
- const volumes = new VolumesResource(transport);
68
-
69
- expect(() =>
70
- volumes.create({
71
- name: 'too-small',
72
- sizeGB: MIN_VOLUME_SIZE_GB - 1,
73
- region: 'region-1',
74
- }),
75
- ).toThrow(`Volume size must be at least ${MIN_VOLUME_SIZE_GB}GB.`);
76
- });
77
-
78
- test('defaults volume type to sandbox when omitted', async () => {
79
- let requestBody: unknown = null;
80
-
81
- const fetchImpl = vi.fn(async (_url: URL | RequestInfo, init?: RequestInit) => {
82
- if (typeof init?.body === 'string') {
83
- requestBody = JSON.parse(init.body) as unknown;
84
- }
85
-
86
- return new Response(
87
- JSON.stringify({
88
- message: 'created',
89
- data: volumeFixture,
90
- }),
91
- {
92
- status: 200,
93
- headers: {
94
- 'content-type': 'application/json',
95
- },
96
- },
97
- );
98
- }) as typeof fetch;
99
-
100
- const transport = new HttpTransport({
101
- baseUrl: 'https://sandbox.brimble.io',
102
- apiKey: 'test-key',
103
- fetchImpl,
104
- });
105
-
106
- const volumes = new VolumesResource(transport);
107
-
108
- const created = await volumes.create({
109
- name: 'workspace',
110
- sizeGB: 20,
111
- region: 'region-1',
112
- });
113
-
114
- expect(created.type).toBe(VolumeType.Sandbox);
115
- expect(requestBody).toMatchObject({
116
- name: 'workspace',
117
- sizeGB: 20,
118
- region: 'region-1',
119
- type: VolumeType.Sandbox,
120
- });
121
- });
122
- });
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "CommonJS",
5
- "moduleResolution": "node",
6
- "lib": ["ES2022", "DOM"],
7
- "declaration": true,
8
- "outDir": "dist",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "resolveJsonModule": true,
12
- "skipLibCheck": true
13
- },
14
- "include": ["src/**/*.ts"],
15
- "exclude": ["dist", "node_modules"]
16
- }
package/vitest.config.ts DELETED
@@ -1,12 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- environment: 'node',
6
- include: ['test/unit/**/*.test.ts'],
7
- testTimeout: 15_000,
8
- hookTimeout: 15_000,
9
- restoreMocks: true,
10
- clearMocks: true,
11
- },
12
- });
@@ -1,15 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- environment: 'node',
6
- include: ['test/integration/**/*.test.ts'],
7
- testTimeout: 240_000,
8
- hookTimeout: 240_000,
9
- restoreMocks: true,
10
- clearMocks: true,
11
- sequence: {
12
- concurrent: false,
13
- },
14
- },
15
- });