@illuma-ai/code-sandbox 1.1.0 → 1.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.
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @illuma-ai/code-sandbox — Type definitions
3
3
  *
4
4
  * Core types for the browser-native code sandbox.
5
- * Covers file maps, runtime states, git operations, and component props.
5
+ * Covers file maps, runtime states, imperative handle, and component props.
6
6
  */
7
7
 
8
8
  // ---------------------------------------------------------------------------
@@ -138,11 +138,9 @@ export interface RuntimeState {
138
138
  files: FileMap;
139
139
  /**
140
140
  * Baseline file snapshot — the files as they were before the latest
141
- * update (initial load, or the version before the last GitHub poll).
142
- *
143
- * Used by the diff viewer to show what changed. Empty on first load
144
- * (everything is "new"), populated after the first file update
145
- * (GitHub poll, updateFiles, etc.).
141
+ * update (via updateFiles). Used by the diff viewer to show what changed.
142
+ * Empty on first load (everything is "new"), populated after the first
143
+ * file update.
146
144
  */
147
145
  originalFiles: FileMap;
148
146
  /**
@@ -163,7 +161,7 @@ export interface RuntimeState {
163
161
  }
164
162
 
165
163
  // ---------------------------------------------------------------------------
166
- // Git (GitHub API integration)
164
+ // Git (GitHub API integration — utility, NOT used internally by sandbox)
167
165
  // ---------------------------------------------------------------------------
168
166
 
169
167
  export interface GitHubRepo {
@@ -199,17 +197,118 @@ export interface GitPRResult {
199
197
  branch: string;
200
198
  }
201
199
 
200
+ // ---------------------------------------------------------------------------
201
+ // Imperative Handle
202
+ // ---------------------------------------------------------------------------
203
+
204
+ /**
205
+ * Imperative handle exposed by CodeSandbox via React.forwardRef.
206
+ *
207
+ * This is the primary API for host applications (like Ranger) to
208
+ * control the sandbox programmatically. The sandbox is a "dumb renderer"
209
+ * — the host pushes files in and reads state out.
210
+ *
211
+ * @example
212
+ * ```tsx
213
+ * const ref = useRef<CodeSandboxHandle>(null);
214
+ *
215
+ * // Push files from any source (GitHub, DB, S3, agent output)
216
+ * ref.current?.updateFiles(fileMap);
217
+ *
218
+ * // Push a single file (e.g., agent modified one file)
219
+ * ref.current?.updateFile('server.js', newContent);
220
+ *
221
+ * // Read current state
222
+ * const files = ref.current?.getFiles();
223
+ * const changes = ref.current?.getChangedFiles();
224
+ * const errors = ref.current?.getErrors();
225
+ * ```
226
+ */
227
+ export interface CodeSandboxHandle {
228
+ /**
229
+ * Replace the entire file set. Diffs against current files, writes only
230
+ * changed files to Nodepod FS, and restarts the server if anything changed.
231
+ *
232
+ * The previous file set becomes `originalFiles` for diff tracking.
233
+ *
234
+ * @param files - Complete new file set
235
+ * @param options - Optional: restartServer (default true)
236
+ */
237
+ updateFiles: (
238
+ files: FileMap,
239
+ options?: { restartServer?: boolean },
240
+ ) => Promise<void>;
241
+
242
+ /**
243
+ * Update a single file. Writes to Nodepod FS and updates state.
244
+ * Does NOT restart the server — call `restart()` manually if needed,
245
+ * or use `updateFiles()` for bulk updates with auto-restart.
246
+ *
247
+ * @param path - File path (e.g., "server.js", "public/index.html")
248
+ * @param content - New file content
249
+ */
250
+ updateFile: (path: string, content: string) => Promise<void>;
251
+
252
+ /**
253
+ * Force restart the server process. Kills the current process
254
+ * and re-runs the entry command.
255
+ */
256
+ restart: () => Promise<void>;
257
+
258
+ /**
259
+ * Get the current file map (all files including edits).
260
+ */
261
+ getFiles: () => FileMap;
262
+
263
+ /**
264
+ * Get only files that have been modified relative to originalFiles.
265
+ * Returns a FileMap containing only the changed files.
266
+ */
267
+ getChangedFiles: () => FileMap;
268
+
269
+ /**
270
+ * Get the per-file change status map (new/modified/deleted).
271
+ * Missing keys should be treated as "unchanged".
272
+ */
273
+ getFileChanges: () => Record<string, FileChangeStatus>;
274
+
275
+ /**
276
+ * Get all structured errors collected during this session.
277
+ */
278
+ getErrors: () => SandboxError[];
279
+
280
+ /**
281
+ * Get the current runtime state snapshot.
282
+ */
283
+ getState: () => RuntimeState;
284
+ }
285
+
202
286
  // ---------------------------------------------------------------------------
203
287
  // Component Props
204
288
  // ---------------------------------------------------------------------------
205
289
 
290
+ /**
291
+ * Props for the CodeSandbox component.
292
+ *
293
+ * The sandbox is a pure renderer — it receives files via props and
294
+ * exposes an imperative handle for programmatic updates. It does NOT
295
+ * interact with any storage backend (GitHub, S3, DB) directly.
296
+ *
297
+ * File sources (for initial load, pick ONE):
298
+ * - `files` — pass a FileMap directly
299
+ * - `template` — use a built-in template name (e.g., "fullstack-starter")
300
+ *
301
+ * For live updates after mount, use the imperative handle:
302
+ * ```tsx
303
+ * const ref = useRef<CodeSandboxHandle>(null);
304
+ * <CodeSandbox ref={ref} files={initialFiles} />
305
+ * // Later:
306
+ * ref.current.updateFiles(newFiles);
307
+ * ```
308
+ */
206
309
  export interface CodeSandboxProps {
207
- /** Pass files directly */
310
+ /** Pass files directly (from any source — GitHub, DB, S3, agent, etc.) */
208
311
  files?: FileMap;
209
- /** OR load from GitHub */
210
- github?: GitHubRepo;
211
- /** GitHub personal access token (for private repos and write-back) */
212
- gitToken?: string;
213
312
  /** OR use a built-in template name */
214
313
  template?: string;
215
314
  /** Command to start the dev server (default inferred from package.json or template) */
@@ -220,9 +319,9 @@ export interface CodeSandboxProps {
220
319
  env?: Record<string, string>;
221
320
 
222
321
  // Callbacks
223
- /** Fires when a file is modified in the editor */
322
+ /** Fires when a file is modified in the editor by the user */
224
323
  onFileChange?: (path: string, content: string) => void;
225
- /** Fires when the dev server is ready */
324
+ /** Fires when the dev server is ready (initial boot or after restart) */
226
325
  onServerReady?: (port: number, url: string) => void;
227
326
  /** Fires on boot progress changes */
228
327
  onProgress?: (progress: BootProgress) => void;
@@ -238,6 +337,12 @@ export interface CodeSandboxProps {
238
337
  * Max 2 auto-fix attempts per error is recommended (see Ranger pattern).
239
338
  */
240
339
  onSandboxError?: (error: SandboxError) => void;
340
+ /**
341
+ * Fires after updateFiles() completes (files written + server restarted).
342
+ * Useful for the host to know when the sandbox has finished processing
343
+ * a file push.
344
+ */
345
+ onFilesUpdated?: (fileChanges: Record<string, FileChangeStatus>) => void;
241
346
 
242
347
  // Layout
243
348
  /** CSS class name for the root element */