@treesap/sandbox 0.2.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 (66) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/README.md +495 -0
  3. package/dist/api-server.d.ts +41 -0
  4. package/dist/api-server.d.ts.map +1 -0
  5. package/dist/api-server.js +536 -0
  6. package/dist/api-server.js.map +1 -0
  7. package/dist/auth-middleware.d.ts +31 -0
  8. package/dist/auth-middleware.d.ts.map +1 -0
  9. package/dist/auth-middleware.js +35 -0
  10. package/dist/auth-middleware.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +65 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/client.d.ts +137 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +412 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/file-service.d.ts +94 -0
  20. package/dist/file-service.d.ts.map +1 -0
  21. package/dist/file-service.js +203 -0
  22. package/dist/file-service.js.map +1 -0
  23. package/dist/http-exposure-service.d.ts +71 -0
  24. package/dist/http-exposure-service.d.ts.map +1 -0
  25. package/dist/http-exposure-service.js +172 -0
  26. package/dist/http-exposure-service.js.map +1 -0
  27. package/dist/index.d.ts +59 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +66 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/sandbox-manager.d.ts +76 -0
  32. package/dist/sandbox-manager.d.ts.map +1 -0
  33. package/dist/sandbox-manager.js +161 -0
  34. package/dist/sandbox-manager.js.map +1 -0
  35. package/dist/sandbox.d.ts +118 -0
  36. package/dist/sandbox.d.ts.map +1 -0
  37. package/dist/sandbox.js +303 -0
  38. package/dist/sandbox.js.map +1 -0
  39. package/dist/server.d.ts +7 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +240 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/stream-service.d.ts +35 -0
  44. package/dist/stream-service.d.ts.map +1 -0
  45. package/dist/stream-service.js +136 -0
  46. package/dist/stream-service.js.map +1 -0
  47. package/dist/terminal.d.ts +46 -0
  48. package/dist/terminal.d.ts.map +1 -0
  49. package/dist/terminal.js +264 -0
  50. package/dist/terminal.js.map +1 -0
  51. package/dist/websocket.d.ts +48 -0
  52. package/dist/websocket.d.ts.map +1 -0
  53. package/dist/websocket.js +332 -0
  54. package/dist/websocket.js.map +1 -0
  55. package/package.json +59 -0
  56. package/src/api-server.ts +658 -0
  57. package/src/auth-middleware.ts +65 -0
  58. package/src/cli.ts +71 -0
  59. package/src/client.ts +537 -0
  60. package/src/file-service.ts +273 -0
  61. package/src/http-exposure-service.ts +232 -0
  62. package/src/index.ts +101 -0
  63. package/src/sandbox-manager.ts +202 -0
  64. package/src/sandbox.ts +396 -0
  65. package/src/stream-service.ts +174 -0
  66. package/tsconfig.json +37 -0
@@ -0,0 +1,94 @@
1
+ import { Readable } from 'stream';
2
+ export interface FileInfo {
3
+ name: string;
4
+ path: string;
5
+ type: 'file' | 'directory';
6
+ size?: number;
7
+ mtime?: number;
8
+ }
9
+ export interface ListFilesOptions {
10
+ recursive?: boolean;
11
+ pattern?: string;
12
+ includeHidden?: boolean;
13
+ }
14
+ export interface ReadFileOptions {
15
+ encoding?: BufferEncoding;
16
+ raw?: boolean;
17
+ }
18
+ export interface WriteFileOptions {
19
+ encoding?: BufferEncoding;
20
+ mode?: number;
21
+ createDirs?: boolean;
22
+ }
23
+ /**
24
+ * Service for managing file operations within a sandbox
25
+ * Includes path validation to prevent directory traversal attacks
26
+ */
27
+ export declare class FileService {
28
+ private basePath;
29
+ constructor(basePath: string);
30
+ /**
31
+ * Validate and resolve a path within the sandbox
32
+ * Prevents directory traversal attacks
33
+ */
34
+ private resolvePath;
35
+ /**
36
+ * Read a file's contents
37
+ */
38
+ readFile(filePath: string, options?: ReadFileOptions): Promise<string | Buffer>;
39
+ /**
40
+ * Write content to a file
41
+ */
42
+ writeFile(filePath: string, content: string | Buffer, options?: WriteFileOptions): Promise<void>;
43
+ /**
44
+ * List files in a directory
45
+ */
46
+ listFiles(dirPath?: string, options?: ListFilesOptions): Promise<FileInfo[]>;
47
+ /**
48
+ * Delete a file or directory
49
+ */
50
+ deleteFile(filePath: string, options?: {
51
+ recursive?: boolean;
52
+ }): Promise<void>;
53
+ /**
54
+ * Check if a file or directory exists
55
+ */
56
+ exists(filePath: string): Promise<boolean>;
57
+ /**
58
+ * Get file stats
59
+ */
60
+ stat(filePath: string): Promise<FileInfo>;
61
+ /**
62
+ * Create a directory
63
+ */
64
+ mkdir(dirPath: string, options?: {
65
+ recursive?: boolean;
66
+ }): Promise<void>;
67
+ /**
68
+ * Copy a file or directory
69
+ */
70
+ copy(sourcePath: string, destPath: string, options?: {
71
+ overwrite?: boolean;
72
+ }): Promise<void>;
73
+ /**
74
+ * Move/rename a file or directory
75
+ */
76
+ move(sourcePath: string, destPath: string): Promise<void>;
77
+ /**
78
+ * Create a readable stream for a file
79
+ */
80
+ createReadStream(filePath: string): Readable;
81
+ /**
82
+ * Create a writable stream for a file
83
+ */
84
+ createWriteStream(filePath: string): NodeJS.WritableStream;
85
+ /**
86
+ * Simple glob pattern matching
87
+ */
88
+ private matchPattern;
89
+ /**
90
+ * Get the base path of this file service
91
+ */
92
+ getBasePath(): string;
93
+ }
94
+ //# sourceMappingURL=file-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-service.d.ts","sourceRoot":"","sources":["../src/file-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAWzF;;OAEG;IACG,SAAS,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAmBhB;;OAEG;IACG,SAAS,CAAC,OAAO,GAAE,MAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgD3F;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxF;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUhD;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAc/C;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlF;;OAEG;IACG,IAAI,CACR,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACpC,OAAO,CAAC,IAAI,CAAC;IAmBhB;;OAEG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/D;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAK5C;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc;IAK1D;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB;;OAEG;IACH,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,203 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { createReadStream, createWriteStream } from 'fs';
4
+ /**
5
+ * Service for managing file operations within a sandbox
6
+ * Includes path validation to prevent directory traversal attacks
7
+ */
8
+ export class FileService {
9
+ basePath;
10
+ constructor(basePath) {
11
+ this.basePath = path.resolve(basePath);
12
+ }
13
+ /**
14
+ * Validate and resolve a path within the sandbox
15
+ * Prevents directory traversal attacks
16
+ */
17
+ resolvePath(filePath) {
18
+ const resolved = path.resolve(this.basePath, filePath);
19
+ // Ensure the resolved path is within basePath
20
+ if (!resolved.startsWith(this.basePath)) {
21
+ throw new Error('Path traversal detected - access denied');
22
+ }
23
+ return resolved;
24
+ }
25
+ /**
26
+ * Read a file's contents
27
+ */
28
+ async readFile(filePath, options = {}) {
29
+ const resolved = this.resolvePath(filePath);
30
+ if (options.raw) {
31
+ return await fs.readFile(resolved);
32
+ }
33
+ const encoding = options.encoding || 'utf-8';
34
+ return await fs.readFile(resolved, encoding);
35
+ }
36
+ /**
37
+ * Write content to a file
38
+ */
39
+ async writeFile(filePath, content, options = {}) {
40
+ const resolved = this.resolvePath(filePath);
41
+ // Create parent directories if requested
42
+ if (options.createDirs) {
43
+ const dir = path.dirname(resolved);
44
+ await fs.mkdir(dir, { recursive: true });
45
+ }
46
+ const encoding = options.encoding || 'utf-8';
47
+ const writeOptions = { encoding };
48
+ if (options.mode) {
49
+ writeOptions.mode = options.mode;
50
+ }
51
+ await fs.writeFile(resolved, content, writeOptions);
52
+ }
53
+ /**
54
+ * List files in a directory
55
+ */
56
+ async listFiles(dirPath = '.', options = {}) {
57
+ const resolved = this.resolvePath(dirPath);
58
+ const files = [];
59
+ const entries = await fs.readdir(resolved, { withFileTypes: true });
60
+ for (const entry of entries) {
61
+ // Skip hidden files unless requested
62
+ if (!options.includeHidden && entry.name.startsWith('.')) {
63
+ continue;
64
+ }
65
+ // Apply pattern filter if provided
66
+ if (options.pattern && !this.matchPattern(entry.name, options.pattern)) {
67
+ continue;
68
+ }
69
+ const fullPath = path.join(resolved, entry.name);
70
+ const relativePath = path.relative(this.basePath, fullPath);
71
+ const fileInfo = {
72
+ name: entry.name,
73
+ path: relativePath,
74
+ type: entry.isDirectory() ? 'directory' : 'file',
75
+ };
76
+ // Get file stats for size and mtime
77
+ try {
78
+ const stats = await fs.stat(fullPath);
79
+ fileInfo.size = stats.size;
80
+ fileInfo.mtime = stats.mtimeMs;
81
+ }
82
+ catch {
83
+ // Ignore stat errors
84
+ }
85
+ files.push(fileInfo);
86
+ // Recursively list subdirectories if requested
87
+ if (options.recursive && entry.isDirectory()) {
88
+ const subFiles = await this.listFiles(relativePath, options);
89
+ files.push(...subFiles);
90
+ }
91
+ }
92
+ return files;
93
+ }
94
+ /**
95
+ * Delete a file or directory
96
+ */
97
+ async deleteFile(filePath, options = {}) {
98
+ const resolved = this.resolvePath(filePath);
99
+ const stats = await fs.stat(resolved);
100
+ if (stats.isDirectory()) {
101
+ await fs.rm(resolved, { recursive: options.recursive, force: true });
102
+ }
103
+ else {
104
+ await fs.unlink(resolved);
105
+ }
106
+ }
107
+ /**
108
+ * Check if a file or directory exists
109
+ */
110
+ async exists(filePath) {
111
+ try {
112
+ const resolved = this.resolvePath(filePath);
113
+ await fs.access(resolved);
114
+ return true;
115
+ }
116
+ catch {
117
+ return false;
118
+ }
119
+ }
120
+ /**
121
+ * Get file stats
122
+ */
123
+ async stat(filePath) {
124
+ const resolved = this.resolvePath(filePath);
125
+ const stats = await fs.stat(resolved);
126
+ const relativePath = path.relative(this.basePath, resolved);
127
+ return {
128
+ name: path.basename(resolved),
129
+ path: relativePath,
130
+ type: stats.isDirectory() ? 'directory' : 'file',
131
+ size: stats.size,
132
+ mtime: stats.mtimeMs,
133
+ };
134
+ }
135
+ /**
136
+ * Create a directory
137
+ */
138
+ async mkdir(dirPath, options = {}) {
139
+ const resolved = this.resolvePath(dirPath);
140
+ await fs.mkdir(resolved, { recursive: options.recursive });
141
+ }
142
+ /**
143
+ * Copy a file or directory
144
+ */
145
+ async copy(sourcePath, destPath, options = {}) {
146
+ const resolvedSource = this.resolvePath(sourcePath);
147
+ const resolvedDest = this.resolvePath(destPath);
148
+ // Check if destination exists
149
+ if (!options.overwrite) {
150
+ try {
151
+ await fs.access(resolvedDest);
152
+ throw new Error('Destination already exists');
153
+ }
154
+ catch (err) {
155
+ if (err.code !== 'ENOENT') {
156
+ throw err;
157
+ }
158
+ }
159
+ }
160
+ await fs.cp(resolvedSource, resolvedDest, { recursive: true });
161
+ }
162
+ /**
163
+ * Move/rename a file or directory
164
+ */
165
+ async move(sourcePath, destPath) {
166
+ const resolvedSource = this.resolvePath(sourcePath);
167
+ const resolvedDest = this.resolvePath(destPath);
168
+ await fs.rename(resolvedSource, resolvedDest);
169
+ }
170
+ /**
171
+ * Create a readable stream for a file
172
+ */
173
+ createReadStream(filePath) {
174
+ const resolved = this.resolvePath(filePath);
175
+ return createReadStream(resolved);
176
+ }
177
+ /**
178
+ * Create a writable stream for a file
179
+ */
180
+ createWriteStream(filePath) {
181
+ const resolved = this.resolvePath(filePath);
182
+ return createWriteStream(resolved);
183
+ }
184
+ /**
185
+ * Simple glob pattern matching
186
+ */
187
+ matchPattern(filename, pattern) {
188
+ // Convert glob pattern to regex
189
+ const regexPattern = pattern
190
+ .replace(/\./g, '\\.')
191
+ .replace(/\*/g, '.*')
192
+ .replace(/\?/g, '.');
193
+ const regex = new RegExp(`^${regexPattern}$`, 'i');
194
+ return regex.test(filename);
195
+ }
196
+ /**
197
+ * Get the base path of this file service
198
+ */
199
+ getBasePath() {
200
+ return this.basePath;
201
+ }
202
+ }
203
+ //# sourceMappingURL=file-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-service.js","sourceRoot":"","sources":["../src/file-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * HTTP Exposure Service
3
+ * Integrates with Caddy Admin API to dynamically expose sandbox ports
4
+ */
5
+ export interface HttpExposureConfig {
6
+ /**
7
+ * Caddy Admin API URL (default: http://localhost:2019)
8
+ */
9
+ caddyAdminUrl: string;
10
+ /**
11
+ * Base domain for sandbox subdomains (e.g., sandbox.yourdomain.com)
12
+ */
13
+ baseDomain: string;
14
+ /**
15
+ * Protocol to use for generated URLs (default: https)
16
+ */
17
+ protocol: 'http' | 'https';
18
+ /**
19
+ * Host where sandbox ports are accessible (default: localhost)
20
+ * This is the internal address Caddy will proxy to
21
+ */
22
+ upstreamHost: string;
23
+ }
24
+ export interface ExposedEndpoint {
25
+ sandboxId: string;
26
+ port: number;
27
+ publicUrl: string;
28
+ routeId: string;
29
+ createdAt: number;
30
+ }
31
+ /**
32
+ * Service for managing HTTP exposure of sandbox ports via Caddy
33
+ */
34
+ export declare class HttpExposureService {
35
+ private config;
36
+ private exposures;
37
+ constructor(config?: Partial<HttpExposureConfig>);
38
+ /**
39
+ * Generate a unique subdomain for a sandbox port
40
+ */
41
+ private generateSubdomain;
42
+ /**
43
+ * Generate a unique route ID for Caddy
44
+ */
45
+ private generateRouteId;
46
+ /**
47
+ * Expose a sandbox port and return the public URL
48
+ */
49
+ expose(sandboxId: string, port: number): Promise<string>;
50
+ /**
51
+ * Remove HTTP exposure for a sandbox port (or all ports if port is undefined)
52
+ */
53
+ unexpose(sandboxId: string, port?: number): Promise<void>;
54
+ /**
55
+ * Get all exposures for a sandbox
56
+ */
57
+ getExposures(sandboxId: string): ExposedEndpoint[];
58
+ /**
59
+ * Get a specific exposure
60
+ */
61
+ getExposure(sandboxId: string, port: number): ExposedEndpoint | undefined;
62
+ /**
63
+ * Get all exposures across all sandboxes
64
+ */
65
+ getAllExposures(): ExposedEndpoint[];
66
+ /**
67
+ * Clean up all exposures for a sandbox (called when sandbox is destroyed)
68
+ */
69
+ cleanup(sandboxId: string): Promise<void>;
70
+ }
71
+ //# sourceMappingURL=http-exposure-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-exposure-service.d.ts","sourceRoot":"","sources":["../src/http-exposure-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAE3B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AASD;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,SAAS,CAA6C;gBAElD,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAYpD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8E9D;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC/D;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE;IAIlD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAKzE;;OAEG;IACH,eAAe,IAAI,eAAe,EAAE;IAQpC;;OAEG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * HTTP Exposure Service
3
+ * Integrates with Caddy Admin API to dynamically expose sandbox ports
4
+ */
5
+ const DEFAULT_CONFIG = {
6
+ caddyAdminUrl: 'http://localhost:2019',
7
+ baseDomain: 'sandbox.localhost',
8
+ protocol: 'https',
9
+ upstreamHost: 'localhost',
10
+ };
11
+ /**
12
+ * Service for managing HTTP exposure of sandbox ports via Caddy
13
+ */
14
+ export class HttpExposureService {
15
+ config;
16
+ exposures = new Map();
17
+ constructor(config = {}) {
18
+ this.config = {
19
+ ...DEFAULT_CONFIG,
20
+ ...config,
21
+ // Allow env vars to override
22
+ caddyAdminUrl: config.caddyAdminUrl || process.env.CADDY_ADMIN_URL || DEFAULT_CONFIG.caddyAdminUrl,
23
+ baseDomain: config.baseDomain || process.env.SANDBOX_DOMAIN || DEFAULT_CONFIG.baseDomain,
24
+ protocol: (config.protocol || process.env.SANDBOX_PROTOCOL || DEFAULT_CONFIG.protocol),
25
+ upstreamHost: config.upstreamHost || process.env.SANDBOX_UPSTREAM_HOST || DEFAULT_CONFIG.upstreamHost,
26
+ };
27
+ }
28
+ /**
29
+ * Generate a unique subdomain for a sandbox port
30
+ */
31
+ generateSubdomain(sandboxId, port) {
32
+ // Use first 8 chars of sandbox ID + port for a shorter, readable subdomain
33
+ const shortId = sandboxId.substring(0, 8);
34
+ return `${shortId}-${port}`;
35
+ }
36
+ /**
37
+ * Generate a unique route ID for Caddy
38
+ */
39
+ generateRouteId(sandboxId, port) {
40
+ return `sandbox-${sandboxId}-${port}`;
41
+ }
42
+ /**
43
+ * Expose a sandbox port and return the public URL
44
+ */
45
+ async expose(sandboxId, port) {
46
+ const subdomain = this.generateSubdomain(sandboxId, port);
47
+ const routeId = this.generateRouteId(sandboxId, port);
48
+ const hostname = `${subdomain}.${this.config.baseDomain}`;
49
+ const publicUrl = `${this.config.protocol}://${hostname}`;
50
+ // Check if already exposed
51
+ const existing = this.getExposure(sandboxId, port);
52
+ if (existing) {
53
+ return existing.publicUrl;
54
+ }
55
+ // Create Caddy route configuration
56
+ const route = {
57
+ '@id': routeId,
58
+ match: [{ host: [hostname] }],
59
+ handle: [
60
+ {
61
+ handler: 'reverse_proxy',
62
+ upstreams: [{ dial: `${this.config.upstreamHost}:${port}` }],
63
+ },
64
+ ],
65
+ };
66
+ try {
67
+ // Add route to Caddy via Admin API
68
+ const response = await fetch(`${this.config.caddyAdminUrl}/config/apps/http/servers/srv0/routes`, {
69
+ method: 'POST',
70
+ headers: { 'Content-Type': 'application/json' },
71
+ body: JSON.stringify(route),
72
+ });
73
+ if (!response.ok) {
74
+ const errorText = await response.text();
75
+ throw new Error(`Failed to add Caddy route: ${errorText}`);
76
+ }
77
+ // Track the exposure
78
+ const endpoint = {
79
+ sandboxId,
80
+ port,
81
+ publicUrl,
82
+ routeId,
83
+ createdAt: Date.now(),
84
+ };
85
+ const sandboxExposures = this.exposures.get(sandboxId) || [];
86
+ sandboxExposures.push(endpoint);
87
+ this.exposures.set(sandboxId, sandboxExposures);
88
+ return publicUrl;
89
+ }
90
+ catch (error) {
91
+ // If Caddy is not available, return a placeholder URL for development
92
+ if (error.cause?.code === 'ECONNREFUSED') {
93
+ console.warn(`Caddy not available at ${this.config.caddyAdminUrl}. Using placeholder URL.`);
94
+ // Still track the exposure locally
95
+ const endpoint = {
96
+ sandboxId,
97
+ port,
98
+ publicUrl: `http://${this.config.upstreamHost}:${port}`,
99
+ routeId,
100
+ createdAt: Date.now(),
101
+ };
102
+ const sandboxExposures = this.exposures.get(sandboxId) || [];
103
+ sandboxExposures.push(endpoint);
104
+ this.exposures.set(sandboxId, sandboxExposures);
105
+ return endpoint.publicUrl;
106
+ }
107
+ throw error;
108
+ }
109
+ }
110
+ /**
111
+ * Remove HTTP exposure for a sandbox port (or all ports if port is undefined)
112
+ */
113
+ async unexpose(sandboxId, port) {
114
+ const endpoints = this.exposures.get(sandboxId) || [];
115
+ const toRemove = port
116
+ ? endpoints.filter((e) => e.port === port)
117
+ : endpoints;
118
+ for (const endpoint of toRemove) {
119
+ try {
120
+ // Remove route from Caddy via Admin API
121
+ const response = await fetch(`${this.config.caddyAdminUrl}/id/${endpoint.routeId}`, { method: 'DELETE' });
122
+ // Ignore 404 errors (route doesn't exist)
123
+ if (!response.ok && response.status !== 404) {
124
+ console.warn(`Failed to remove Caddy route ${endpoint.routeId}: ${response.status}`);
125
+ }
126
+ }
127
+ catch (error) {
128
+ // Ignore connection errors (Caddy not available)
129
+ if (error.cause?.code !== 'ECONNREFUSED') {
130
+ console.warn(`Error removing Caddy route: ${error.message}`);
131
+ }
132
+ }
133
+ }
134
+ // Update local tracking
135
+ if (port) {
136
+ this.exposures.set(sandboxId, endpoints.filter((e) => e.port !== port));
137
+ }
138
+ else {
139
+ this.exposures.delete(sandboxId);
140
+ }
141
+ }
142
+ /**
143
+ * Get all exposures for a sandbox
144
+ */
145
+ getExposures(sandboxId) {
146
+ return this.exposures.get(sandboxId) || [];
147
+ }
148
+ /**
149
+ * Get a specific exposure
150
+ */
151
+ getExposure(sandboxId, port) {
152
+ const endpoints = this.exposures.get(sandboxId) || [];
153
+ return endpoints.find((e) => e.port === port);
154
+ }
155
+ /**
156
+ * Get all exposures across all sandboxes
157
+ */
158
+ getAllExposures() {
159
+ const all = [];
160
+ for (const endpoints of this.exposures.values()) {
161
+ all.push(...endpoints);
162
+ }
163
+ return all;
164
+ }
165
+ /**
166
+ * Clean up all exposures for a sandbox (called when sandbox is destroyed)
167
+ */
168
+ async cleanup(sandboxId) {
169
+ await this.unexpose(sandboxId);
170
+ }
171
+ }
172
+ //# sourceMappingURL=http-exposure-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-exposure-service.js","sourceRoot":"","sources":["../src/http-exposure-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * TreeSap Sandbox v1.0
3
+ *
4
+ * A self-hosted sandbox API for isolated code execution and file management.
5
+ * Provides a Cloudflare-style API for managing sandboxed environments.
6
+ *
7
+ * @example Server usage
8
+ * ```typescript
9
+ * import { startServer } from '@treesap/sandbox';
10
+ *
11
+ * // Start the sandbox server
12
+ * const { server, manager } = await startServer({
13
+ * port: 3000,
14
+ * basePath: './.sandboxes'
15
+ * });
16
+ * ```
17
+ *
18
+ * @example Client SDK usage
19
+ * ```typescript
20
+ * import { SandboxClient } from '@treesap/sandbox';
21
+ *
22
+ * // Create a new sandbox
23
+ * const sandbox = await SandboxClient.create('http://localhost:3000');
24
+ *
25
+ * // Execute commands
26
+ * const result = await sandbox.exec('npm install');
27
+ * console.log(result.stdout);
28
+ *
29
+ * // File operations
30
+ * await sandbox.writeFile('package.json', JSON.stringify(pkg, null, 2));
31
+ * const files = await sandbox.listFiles();
32
+ *
33
+ * // Process management
34
+ * const server = await sandbox.startProcess('node server.js');
35
+ * const logs = await sandbox.streamProcessLogs(server.id);
36
+ *
37
+ * // Cleanup
38
+ * await sandbox.destroy({ cleanup: true });
39
+ * ```
40
+ *
41
+ * @packageDocumentation
42
+ */
43
+ export { startServer, createServer } from './api-server';
44
+ export type { ServerConfig } from './api-server';
45
+ export { SandboxClient, parseSSEStream } from './client';
46
+ export type { SandboxClientConfig, CreateSandboxResponse } from './client';
47
+ export { Sandbox } from './sandbox';
48
+ export { SandboxManager } from './sandbox-manager';
49
+ export { FileService } from './file-service';
50
+ export { StreamService } from './stream-service';
51
+ export type { SandboxConfig, ProcessInfo, ExecOptions, ExecuteResponse, } from './sandbox';
52
+ export type { SandboxManagerConfig } from './sandbox-manager';
53
+ export type { FileInfo, ListFilesOptions, ReadFileOptions, WriteFileOptions, } from './file-service';
54
+ export type { ExecEvent, ExecEventType, LogEvent } from './stream-service';
55
+ export { createAuthMiddleware, parseApiKeysFromEnv } from './auth-middleware';
56
+ export type { AuthConfig } from './auth-middleware';
57
+ export { HttpExposureService } from './http-exposure-service';
58
+ export type { HttpExposureConfig, ExposedEndpoint } from './http-exposure-service';
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAMH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAM3E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjD,YAAY,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,YAAY,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM3E,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}