oblien 1.3.0 → 2.0.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 (187) hide show
  1. package/dist/client.d.ts +31 -0
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/client.js +33 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/error.d.ts +29 -0
  6. package/dist/error.d.ts.map +1 -0
  7. package/dist/error.js +52 -0
  8. package/dist/error.js.map +1 -0
  9. package/dist/http.d.ts +20 -0
  10. package/dist/http.d.ts.map +1 -0
  11. package/dist/http.js +108 -0
  12. package/dist/http.js.map +1 -0
  13. package/dist/index.d.ts +8 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +10 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/resources/api-access.d.ts +21 -0
  18. package/dist/resources/api-access.d.ts.map +1 -0
  19. package/dist/resources/api-access.js +32 -0
  20. package/dist/resources/api-access.js.map +1 -0
  21. package/dist/resources/base.d.ts +17 -0
  22. package/dist/resources/base.d.ts.map +1 -0
  23. package/dist/resources/base.js +21 -0
  24. package/dist/resources/base.js.map +1 -0
  25. package/dist/resources/images.d.ts +11 -0
  26. package/dist/resources/images.d.ts.map +1 -0
  27. package/dist/resources/images.js +16 -0
  28. package/dist/resources/images.js.map +1 -0
  29. package/dist/resources/lifecycle.d.ts +23 -0
  30. package/dist/resources/lifecycle.d.ts.map +1 -0
  31. package/dist/resources/lifecycle.js +32 -0
  32. package/dist/resources/lifecycle.js.map +1 -0
  33. package/dist/resources/logs.d.ts +25 -0
  34. package/dist/resources/logs.d.ts.map +1 -0
  35. package/dist/resources/logs.js +51 -0
  36. package/dist/resources/logs.js.map +1 -0
  37. package/dist/resources/metadata.d.ts +15 -0
  38. package/dist/resources/metadata.d.ts.map +1 -0
  39. package/dist/resources/metadata.js +20 -0
  40. package/dist/resources/metadata.js.map +1 -0
  41. package/dist/resources/metrics.d.ts +17 -0
  42. package/dist/resources/metrics.d.ts.map +1 -0
  43. package/dist/resources/metrics.js +27 -0
  44. package/dist/resources/metrics.js.map +1 -0
  45. package/dist/resources/network.d.ts +17 -0
  46. package/dist/resources/network.d.ts.map +1 -0
  47. package/dist/resources/network.js +20 -0
  48. package/dist/resources/network.js.map +1 -0
  49. package/dist/resources/public-access.d.ts +15 -0
  50. package/dist/resources/public-access.d.ts.map +1 -0
  51. package/dist/resources/public-access.js +21 -0
  52. package/dist/resources/public-access.js.map +1 -0
  53. package/dist/resources/resources.d.ts +15 -0
  54. package/dist/resources/resources.d.ts.map +1 -0
  55. package/dist/resources/resources.js +20 -0
  56. package/dist/resources/resources.js.map +1 -0
  57. package/dist/resources/snapshots.d.ts +27 -0
  58. package/dist/resources/snapshots.d.ts.map +1 -0
  59. package/dist/resources/snapshots.js +45 -0
  60. package/dist/resources/snapshots.js.map +1 -0
  61. package/dist/resources/ssh.d.ts +19 -0
  62. package/dist/resources/ssh.d.ts.map +1 -0
  63. package/dist/resources/ssh.js +28 -0
  64. package/dist/resources/ssh.js.map +1 -0
  65. package/dist/resources/usage.d.ts +25 -0
  66. package/dist/resources/usage.d.ts.map +1 -0
  67. package/dist/resources/usage.js +44 -0
  68. package/dist/resources/usage.js.map +1 -0
  69. package/dist/resources/workloads.d.ts +39 -0
  70. package/dist/resources/workloads.d.ts.map +1 -0
  71. package/dist/resources/workloads.js +83 -0
  72. package/dist/resources/workloads.js.map +1 -0
  73. package/dist/runtime/exec.d.ts +71 -0
  74. package/dist/runtime/exec.d.ts.map +1 -0
  75. package/dist/runtime/exec.js +163 -0
  76. package/dist/runtime/exec.js.map +1 -0
  77. package/dist/runtime/files.d.ts +39 -0
  78. package/dist/runtime/files.d.ts.map +1 -0
  79. package/dist/runtime/files.js +143 -0
  80. package/dist/runtime/files.js.map +1 -0
  81. package/dist/runtime/search.d.ts +23 -0
  82. package/dist/runtime/search.d.ts.map +1 -0
  83. package/dist/runtime/search.js +65 -0
  84. package/dist/runtime/search.js.map +1 -0
  85. package/dist/runtime/terminal.d.ts +29 -0
  86. package/dist/runtime/terminal.d.ts.map +1 -0
  87. package/dist/runtime/terminal.js +58 -0
  88. package/dist/runtime/terminal.js.map +1 -0
  89. package/dist/runtime/watcher.d.ts +27 -0
  90. package/dist/runtime/watcher.d.ts.map +1 -0
  91. package/dist/runtime/watcher.js +53 -0
  92. package/dist/runtime/watcher.js.map +1 -0
  93. package/dist/runtime/ws.d.ts +92 -0
  94. package/dist/runtime/ws.d.ts.map +1 -0
  95. package/dist/runtime/ws.js +228 -0
  96. package/dist/runtime/ws.js.map +1 -0
  97. package/dist/runtime-http.d.ts +35 -0
  98. package/dist/runtime-http.d.ts.map +1 -0
  99. package/dist/runtime-http.js +99 -0
  100. package/dist/runtime-http.js.map +1 -0
  101. package/dist/runtime.d.ts +77 -0
  102. package/dist/runtime.d.ts.map +1 -0
  103. package/dist/runtime.js +97 -0
  104. package/dist/runtime.js.map +1 -0
  105. package/dist/types/client.d.ts +7 -0
  106. package/dist/types/client.d.ts.map +1 -0
  107. package/dist/types/client.js +3 -0
  108. package/dist/types/client.js.map +1 -0
  109. package/dist/types/common.d.ts +13 -0
  110. package/dist/types/common.d.ts.map +1 -0
  111. package/dist/types/common.js +3 -0
  112. package/dist/types/common.js.map +1 -0
  113. package/dist/types/index.d.ts +8 -0
  114. package/dist/types/index.d.ts.map +1 -0
  115. package/dist/types/index.js +2 -0
  116. package/dist/types/index.js.map +1 -0
  117. package/dist/types/network.d.ts +15 -0
  118. package/dist/types/network.d.ts.map +1 -0
  119. package/dist/types/network.js +3 -0
  120. package/dist/types/network.js.map +1 -0
  121. package/dist/types/resources.d.ts +10 -0
  122. package/dist/types/resources.d.ts.map +1 -0
  123. package/dist/types/resources.js +3 -0
  124. package/dist/types/resources.js.map +1 -0
  125. package/dist/types/runtime.d.ts +302 -0
  126. package/dist/types/runtime.d.ts.map +1 -0
  127. package/dist/types/runtime.js +3 -0
  128. package/dist/types/runtime.js.map +1 -0
  129. package/dist/types/workspace-resources.d.ts +186 -0
  130. package/dist/types/workspace-resources.d.ts.map +1 -0
  131. package/dist/types/workspace-resources.js +3 -0
  132. package/dist/types/workspace-resources.js.map +1 -0
  133. package/dist/types/workspace.d.ts +41 -0
  134. package/dist/types/workspace.d.ts.map +1 -0
  135. package/dist/types/workspace.js +3 -0
  136. package/dist/types/workspace.js.map +1 -0
  137. package/dist/workspace.d.ts +135 -0
  138. package/dist/workspace.d.ts.map +1 -0
  139. package/dist/workspace.js +194 -0
  140. package/dist/workspace.js.map +1 -0
  141. package/package.json +30 -69
  142. package/LICENSE +0 -21
  143. package/README.md +0 -574
  144. package/agents.js +0 -14
  145. package/browser.js +0 -6
  146. package/cdn.js +0 -6
  147. package/chat.js +0 -21
  148. package/credits.js +0 -11
  149. package/icons.js +0 -11
  150. package/index.d.ts +0 -986
  151. package/index.js +0 -63
  152. package/namespaces.js +0 -12
  153. package/sandbox.js +0 -12
  154. package/search.js +0 -11
  155. package/src/agents/agent.js +0 -229
  156. package/src/agents/index.js +0 -227
  157. package/src/agents/settings.js +0 -100
  158. package/src/agents/tools.js +0 -155
  159. package/src/browser/index.js +0 -474
  160. package/src/cdn/index.js +0 -769
  161. package/src/chat/index.js +0 -724
  162. package/src/chat/session.js +0 -93
  163. package/src/client.js +0 -175
  164. package/src/credits/index.js +0 -492
  165. package/src/icons/index.js +0 -185
  166. package/src/namespaces/index.js +0 -236
  167. package/src/namespaces/namespace.js +0 -274
  168. package/src/sandbox/core/api/base.js +0 -89
  169. package/src/sandbox/core/api/database.js +0 -340
  170. package/src/sandbox/core/api/files.js +0 -141
  171. package/src/sandbox/core/api/git.js +0 -174
  172. package/src/sandbox/core/api/search.js +0 -29
  173. package/src/sandbox/core/api/snapshots.js +0 -132
  174. package/src/sandbox/core/api/terminal.js +0 -20
  175. package/src/sandbox/core/auth.js +0 -256
  176. package/src/sandbox/core/client.js +0 -197
  177. package/src/sandbox/core/index.js +0 -22
  178. package/src/sandbox/core/managers/terminal.js +0 -453
  179. package/src/sandbox/core/managers/watcher.js +0 -197
  180. package/src/sandbox/core/types.js +0 -92
  181. package/src/sandbox/core/utils/http.js +0 -89
  182. package/src/sandbox/core/websocket/connection.js +0 -479
  183. package/src/sandbox/index.d.ts +0 -542
  184. package/src/sandbox/index.js +0 -234
  185. package/src/sandbox/sandbox.js +0 -313
  186. package/src/search/index.js +0 -206
  187. package/src/utils/guest-manager.js +0 -454
@@ -1,453 +0,0 @@
1
- /**
2
- * Terminal Manager
3
- * Clean terminal management with shared WebSocket connection
4
- * Terminal list is fetched from backend, not stored locally
5
- */
6
-
7
- /**
8
- * Terminal Manager - Manages terminal operations
9
- */
10
- export class TerminalManager {
11
- /**
12
- * @param {WebSocketConnection} connection - Shared WebSocket connection
13
- */
14
- constructor(connection) {
15
- this.connection = connection;
16
- }
17
-
18
- /**
19
- * Ensure WebSocket is connected
20
- * @private
21
- */
22
- async _ensureConnected() {
23
- if (!this.connection.connected) {
24
- await this.connection.connect();
25
- }
26
- }
27
-
28
- /**
29
- * Execute a command and get the result (one-off execution)
30
- * @param {Object} options - Execution options
31
- * @param {string} options.command - Command to execute
32
- * @param {Array<string>} [options.args] - Command arguments
33
- * @param {string} [options.cwd] - Working directory
34
- * @param {number} [options.timeout=30000] - Execution timeout
35
- * @param {number} [options.terminalId=0] - Terminal ID to use
36
- * @returns {Promise<string>} Command output (stripped of ANSI codes)
37
- *
38
- * @example
39
- * ```javascript
40
- * // Simple command execution
41
- * const output = await sandbox.terminal.execute({
42
- * command: 'npm install'
43
- * });
44
- * console.log(output);
45
- *
46
- * // With arguments
47
- * const files = await sandbox.terminal.execute({
48
- * command: 'ls',
49
- * args: ['-la', '/opt/app']
50
- * });
51
- * ```
52
- */
53
- async execute(options) {
54
- if (!options.command) {
55
- throw new Error('command is required');
56
- }
57
-
58
- await this._ensureConnected();
59
-
60
- const message = {
61
- action: 'terminal_create',
62
- terminalId: options.terminalId || 0,
63
- command: options.command,
64
- args: options.args || [],
65
- task: true,
66
- force: true,
67
- withLogs: true,
68
- awaitFinish: true,
69
- timeout: options.timeout || 30000,
70
- cols: 120,
71
- rows: 30
72
- };
73
-
74
- if (options.cwd) message.cwd = options.cwd;
75
-
76
- const response = await this.connection.sendRequest(message);
77
-
78
- if (response.error) {
79
- return response
80
- }
81
-
82
- return {
83
- exitCode: response.exit?.code?.exitCode || response.exit?.code || response.exitCode || 0,
84
- signal: response.exit?.code?.signal || response.exit?.signal || response.signal || 0,
85
- logs: Buffer.from(response.logs || '', 'base64').toString('utf-8')
86
- };
87
- }
88
-
89
- /**
90
- * Create a new interactive terminal (live access with callbacks)
91
- * @param {Object} [options] - Terminal options
92
- * @param {number} [options.terminalId] - Specific terminal ID (auto-generated if not provided)
93
- * @param {number} [options.cols=120] - Terminal columns
94
- * @param {number} [options.rows=30] - Terminal rows
95
- * @param {string} [options.cwd] - Working directory
96
- * @param {Function} [options.onData] - Data callback for real-time output
97
- * @param {Function} [options.onExit] - Exit callback
98
- * @returns {Promise<Terminal>} Terminal instance for interactive use
99
- *
100
- * @example
101
- * ```javascript
102
- * // Interactive terminal with real-time output
103
- * const terminal = await sandbox.terminal.create({
104
- * onData: (data) => process.stdout.write(data),
105
- * onExit: (code, signal) => console.log('Exited:', code)
106
- * });
107
- *
108
- * // Write commands
109
- * terminal.write('cd /opt/app\n');
110
- * terminal.write('npm install\n');
111
- *
112
- * // Later...
113
- * await terminal.close();
114
- * ```
115
- */
116
- async create(options = {}) {
117
- await this._ensureConnected();
118
-
119
- // Build message for interactive terminal
120
- const message = {
121
- action: 'terminal_create',
122
- cols: options.cols || 120,
123
- rows: options.rows || 30,
124
- force: options.force || false
125
- };
126
-
127
- // Only include optional fields if provided
128
- if (options.terminalId !== undefined) message.terminalId = options.terminalId;
129
- if (options.cwd) message.cwd = options.cwd;
130
-
131
- const response = await this.connection.sendRequest(message);
132
-
133
- if (response.error) {
134
- return response
135
- }
136
-
137
- // Create interactive terminal instance
138
- const terminal = new Terminal(this.connection, response.terminalId, options);
139
-
140
- // Store response data
141
- terminal.cols = response.cols;
142
- terminal.rows = response.rows;
143
- terminal.cwd = response.cwd;
144
- terminal.existing = response.existing || false;
145
-
146
- return terminal;
147
- }
148
-
149
- /**
150
- * List active terminals (fetched from backend)
151
- * @returns {Promise<Array>} Terminal list
152
- *
153
- * @example
154
- * ```javascript
155
- * const terminals = await sandbox.terminal.list();
156
- * console.log(terminals); // [{ id: 1 }, { id: 2 }]
157
- * ```
158
- */
159
- async list() {
160
- await this._ensureConnected();
161
-
162
- const response = await this.connection.sendRequest({
163
- action: 'terminal_list'
164
- });
165
-
166
- if (response.error) {
167
- return response
168
- }
169
-
170
- return response.terminals || [];
171
- }
172
-
173
- /**
174
- * Get existing terminal by ID
175
- * @param {number} terminalId - Terminal ID
176
- * @param {Object} [options] - Terminal options
177
- * @param {Function} [options.onData] - Data callback
178
- * @param {Function} [options.onExit] - Exit callback
179
- * @returns {Terminal} Terminal instance
180
- *
181
- * @example
182
- * ```javascript
183
- * const terminal = sandbox.terminal.get(1, {
184
- * onData: (data) => console.log(data)
185
- * });
186
- * terminal.write('ls\n');
187
- * ```
188
- */
189
- get(terminalId, options = {}) {
190
- return new Terminal(this.connection, terminalId, options);
191
- }
192
-
193
- /**
194
- * Close a terminal
195
- * @param {number} terminalId - Terminal ID
196
- * @param {boolean} [force=true] - Force close
197
- * @returns {Promise<void>}
198
- *
199
- * @example
200
- * ```javascript
201
- * await sandbox.terminal.close(1);
202
- * ```
203
- */
204
- async close(terminalId, force = true) {
205
- await this._ensureConnected();
206
-
207
- const response = await this.connection.sendRequest({
208
- action: 'terminal_close',
209
- terminalId,
210
- force
211
- });
212
-
213
- if (response.type === 'terminal_error' || response.error) {
214
- return response
215
- }
216
-
217
- if (response.type === 'terminal_closed') {
218
- return true;
219
- }
220
-
221
- return false;
222
- }
223
-
224
- /**
225
- * Disconnect WebSocket (use with caution)
226
- */
227
- disconnect() {
228
- this.connection.disconnect();
229
- }
230
- }
231
-
232
- /**
233
- * Terminal instance representing a single terminal
234
- */
235
- export class Terminal {
236
- /**
237
- * @param {WebSocketConnection} connection - WebSocket connection
238
- * @param {number} terminalId - Terminal ID
239
- * @param {Object} [options] - Terminal options
240
- * @param {Function} [options.onData] - Data callback
241
- * @param {Function} [options.onExit] - Exit callback
242
- */
243
- constructor(connection, terminalId, options = {}) {
244
- this.connection = connection;
245
- this.id = terminalId;
246
- this.onDataCallback = options.onData;
247
- this.onExitCallback = options.onExit;
248
- this._dataHandler = null;
249
- this._exitHandler = null;
250
-
251
- // Set up event listeners if callbacks provided
252
- if (this.onDataCallback) {
253
- this._dataHandler = (output) => {
254
- const text = new TextDecoder().decode(output);
255
- this.onDataCallback(text);
256
- };
257
- this.connection.on(`terminal:${this.id}`, this._dataHandler);
258
- }
259
-
260
- if (this.onExitCallback) {
261
- this._exitHandler = (message) => {
262
- if (message.terminalId === this.id) {
263
- this.onExitCallback(message.exitCode, message.signal);
264
- // Clean up listeners after exit
265
- this._cleanup();
266
- }
267
- };
268
- this.connection.on('terminal_exited', this._exitHandler);
269
- }
270
- }
271
-
272
- /**
273
- * Write data to terminal
274
- * @param {string} data - Data to write
275
- *
276
- * @example
277
- * ```javascript
278
- * terminal.write('ls -la\n');
279
- * ```
280
- */
281
- write(data) {
282
- this.connection.send({
283
- a: 'i', // action: input
284
- id: this.id,
285
- d: data
286
- });
287
- }
288
-
289
- /**
290
- * Resize terminal
291
- * @param {number} cols - Columns
292
- * @param {number} rows - Rows
293
- * @returns {Promise<void>}
294
- *
295
- * @example
296
- * ```javascript
297
- * await terminal.resize(100, 50);
298
- * ```
299
- */
300
- async resize(cols, rows) {
301
- const response = await this.connection.sendRequest({
302
- a: 'r', // action: resize
303
- id: this.id,
304
- cols,
305
- rows
306
- });
307
-
308
- if (response.type === 'terminal_error' || response.error) {
309
- return response
310
- }
311
-
312
- if (response.type === 'terminal_resized') {
313
- this.cols = response.cols;
314
- this.rows = response.rows;
315
- }
316
- }
317
-
318
- /**
319
- * Get terminal state/output
320
- * @param {Object} [options] - State options
321
- * @param {boolean} [options.newOnly=false] - Get only new content since last fetch
322
- * @param {number} [options.maxLines=100] - Maximum lines to return
323
- * @param {string} [options.direction='bottom'] - Direction to get lines (top/bottom)
324
- * @returns {Promise<string>} Terminal state (base64 encoded)
325
- *
326
- * @example
327
- * ```javascript
328
- * const state = await terminal.getState({ newOnly: true });
329
- * const output = Buffer.from(state, 'base64').toString('utf-8');
330
- * console.log(output);
331
- * ```
332
- */
333
- async getState(options = {}) {
334
- const response = await this.connection.sendRequest({
335
- action: 'get_state',
336
- id: this.id,
337
- newOnly: options.newOnly || false,
338
- maxLines: options.maxLines || 100,
339
- direction: options.direction || 'bottom'
340
- });
341
-
342
- if (response.type === 'terminal_error' || response.error) {
343
- return response
344
- }
345
-
346
- if (response.type !== 'terminal_state') {
347
- return response
348
- }
349
-
350
- return {
351
- state: response.state,
352
- newOnly: response.newOnly,
353
- hasNewContent: response.hasNewContent,
354
- linesCount: response.linesCount
355
- };
356
- }
357
-
358
- /**
359
- * Set or update data callback
360
- * @param {Function} callback - Callback function
361
- *
362
- * @example
363
- * ```javascript
364
- * terminal.onData((data) => {
365
- * console.log('Terminal output:', data);
366
- * });
367
- * ```
368
- */
369
- onData(callback) {
370
- // Remove old handler if exists
371
- if (this._dataHandler) {
372
- this.connection.off(`terminal:${this.id}`, this._dataHandler);
373
- }
374
-
375
- // Set new handler
376
- this.onDataCallback = callback;
377
- this._dataHandler = (output) => {
378
- const text = new TextDecoder().decode(output);
379
- this.onDataCallback(text);
380
- };
381
- this.connection.on(`terminal:${this.id}`, this._dataHandler);
382
- }
383
-
384
- /**
385
- * Set or update exit callback
386
- * @param {Function} callback - Callback function
387
- *
388
- * @example
389
- * ```javascript
390
- * terminal.onExit((code, signal) => {
391
- * console.log('Terminal exited:', code, signal);
392
- * });
393
- * ```
394
- */
395
- onExit(callback) {
396
- // Remove old handler if exists
397
- if (this._exitHandler) {
398
- this.connection.off('terminal_exited', this._exitHandler);
399
- }
400
-
401
- // Set new handler
402
- this.onExitCallback = callback;
403
- this._exitHandler = (message) => {
404
- if (message.terminalId === this.id) {
405
- this.onExitCallback(message.exitCode, message.signal);
406
- this._cleanup();
407
- }
408
- };
409
- this.connection.on('terminal_exited', this._exitHandler);
410
- }
411
-
412
- /**
413
- * Close this terminal
414
- * @param {boolean} [force=true] - Force close
415
- * @returns {Promise<void>}
416
- *
417
- * @example
418
- * ```javascript
419
- * await terminal.close();
420
- * ```
421
- */
422
- async close(force = true) {
423
- const response = await this.connection.sendRequest({
424
- action: 'terminal_close',
425
- terminalId: this.id,
426
- force
427
- });
428
-
429
- if (response.type === 'terminal_error' || response.error) {
430
- return response
431
- }
432
-
433
- if (response.type === 'terminal_closed') {
434
- // Clean up listeners
435
- this._cleanup();
436
- }
437
- }
438
-
439
- /**
440
- * Clean up event listeners
441
- * @private
442
- */
443
- _cleanup() {
444
- if (this._dataHandler) {
445
- this.connection.off(`terminal:${this.id}`, this._dataHandler);
446
- this._dataHandler = null;
447
- }
448
- if (this._exitHandler) {
449
- this.connection.off('terminal_exited', this._exitHandler);
450
- this._exitHandler = null;
451
- }
452
- }
453
- }
@@ -1,197 +0,0 @@
1
- /**
2
- * File Watcher Manager
3
- * Clean file watching with shared WebSocket connection
4
- */
5
-
6
- export class WatcherManager {
7
- /**
8
- * @param {WebSocketConnection} connection - Shared WebSocket connection
9
- */
10
- constructor(connection) {
11
- this.connection = connection;
12
- this.isWatching = false;
13
- this.handlers = {
14
- add: [],
15
- change: [],
16
- unlink: [],
17
- error: []
18
- };
19
-
20
- // Set up event listeners on connection
21
- this._setupEventListeners();
22
- }
23
-
24
- /**
25
- * Setup event listeners on WebSocket connection
26
- * @private
27
- */
28
- _setupEventListeners() {
29
- this.connection.on('watch_add', (message) => this._emit('add', message.path));
30
- this.connection.on('watch_change', (message) => this._emit('change', message.path));
31
- this.connection.on('watch_unlink', (message) => this._emit('unlink', message.path));
32
- this.connection.on('watch_error', (message) => this._emit('error', message.path));
33
- }
34
-
35
- /**
36
- * Ensure WebSocket is connected
37
- * @private
38
- */
39
- async _ensureConnected() {
40
- if (!this.connection.connected) {
41
- await this.connection.connect();
42
- }
43
- }
44
-
45
- /**
46
- * Start watching files
47
- * @param {Object} [options] - Watch options
48
- * @param {Array<string>} [options.ignorePatterns] - Patterns to ignore
49
- * @param {Function} [options.onChange] - Change callback
50
- * @param {Function} [options.onAdd] - Add callback
51
- * @param {Function} [options.onUnlink] - Unlink callback
52
- * @param {Function} [options.onError] - Error callback
53
- * @returns {Promise<void>}
54
- *
55
- * @example
56
- * ```javascript
57
- * await sandbox.watcher.start({
58
- * ignorePatterns: ['node_modules', 'dist', '.git'],
59
- * onChange: (path) => console.log('File changed:', path),
60
- * onAdd: (path) => console.log('File added:', path),
61
- * onUnlink: (path) => console.log('File deleted:', path)
62
- * });
63
- * ```
64
- */
65
- async start(options = {}) {
66
- if (this.isWatching) {
67
- console.warn('[Watcher] Already watching files');
68
- return;
69
- }
70
-
71
- await this._ensureConnected();
72
-
73
- // Send watch start message
74
- this.connection.send({
75
- type: 'watch',
76
- ignorePatterns: options.ignorePatterns || []
77
- });
78
-
79
- this.isWatching = true;
80
-
81
- // Register callbacks if provided
82
- if (options.onChange) this.on('change', options.onChange);
83
- if (options.onAdd) this.on('add', options.onAdd);
84
- if (options.onUnlink) this.on('unlink', options.onUnlink);
85
- if (options.onError) this.on('error', options.onError);
86
-
87
- console.log('[Watcher] Started watching files');
88
- }
89
-
90
- /**
91
- * Stop watching files
92
- *
93
- * @example
94
- * ```javascript
95
- * sandbox.watcher.stop();
96
- * ```
97
- */
98
- stop() {
99
- if (!this.isWatching) {
100
- return;
101
- }
102
-
103
- if (this.connection.connected) {
104
- this.connection.send({
105
- type: 'stop_watch'
106
- });
107
- }
108
-
109
- this.isWatching = false;
110
-
111
- // Clear all handlers
112
- this.handlers = {
113
- add: [],
114
- change: [],
115
- unlink: [],
116
- error: []
117
- };
118
-
119
- console.log('[Watcher] Stopped watching files');
120
- }
121
-
122
- /**
123
- * Register event handler
124
- * @param {string} event - Event type (add, change, unlink, error)
125
- * @param {Function} handler - Handler function
126
- *
127
- * @example
128
- * ```javascript
129
- * sandbox.watcher.on('change', (path) => {
130
- * console.log('File changed:', path);
131
- * });
132
- * ```
133
- */
134
- on(event, handler) {
135
- if (!this.handlers[event]) {
136
- console.warn(`[Watcher] Unknown event type: ${event}`);
137
- return;
138
- }
139
- this.handlers[event].push(handler);
140
- }
141
-
142
- /**
143
- * Remove event handler
144
- * @param {string} event - Event type
145
- * @param {Function} handler - Handler function
146
- *
147
- * @example
148
- * ```javascript
149
- * const handler = (path) => console.log(path);
150
- * sandbox.watcher.on('change', handler);
151
- * // Later...
152
- * sandbox.watcher.off('change', handler);
153
- * ```
154
- */
155
- off(event, handler) {
156
- if (!this.handlers[event]) {
157
- return;
158
- }
159
-
160
- const index = this.handlers[event].indexOf(handler);
161
- if (index > -1) {
162
- this.handlers[event].splice(index, 1);
163
- }
164
- }
165
-
166
- /**
167
- * Emit event to all registered handlers
168
- * @private
169
- */
170
- _emit(event, ...args) {
171
- if (this.handlers[event]) {
172
- this.handlers[event].forEach(handler => {
173
- try {
174
- handler(...args);
175
- } catch (error) {
176
- console.error(`[Watcher] Error in ${event} handler:`, error);
177
- }
178
- });
179
- }
180
- }
181
-
182
- /**
183
- * Check if watcher is active
184
- * @returns {boolean}
185
- */
186
- get active() {
187
- return this.isWatching;
188
- }
189
-
190
- /**
191
- * Disconnect WebSocket (use with caution)
192
- */
193
- disconnect() {
194
- this.stop();
195
- this.connection.disconnect();
196
- }
197
- }