11import { readFileSync } from "node:fs" ;
22import { basename , extname } from "node:path" ;
3- import { CodizeApiError , CodizeClient } from "@codize/sdk" ;
3+ import {
4+ CodizeApiError ,
5+ CodizeClient ,
6+ type SandboxExecuteResponse ,
7+ type SandboxRuntime ,
8+ } from "@codize/sdk" ;
49import type { Command } from "commander" ;
510import { readConfig } from "../config.ts" ;
611import { CliError } from "../error.ts" ;
712
8- const EXTENSION_TO_LANGUAGE : Record < string , string > = {
9- ".ts" : "typescript" ,
10- ".js" : "javascript " ,
13+ const EXTENSION_TO_RUNTIME : Record < string , SandboxRuntime > = {
14+ ".ts" : "node- typescript" ,
15+ ".js" : "node " ,
1116 ".py" : "python" ,
1217 ".rb" : "ruby" ,
1318 ".go" : "go" ,
1419 ".rs" : "rust" ,
20+ ".sh" : "bash" ,
1521} ;
1622
17- const LANGUAGE_TO_EXTENSION : Record < string , string > = {
18- typescript : ".ts" ,
19- javascript : ".js" ,
23+ const RUNTIME_TO_EXTENSION : Record < SandboxRuntime , string > = {
24+ "node- typescript" : ".ts" ,
25+ node : ".js" ,
2026 python : ".py" ,
2127 ruby : ".rb" ,
2228 go : ".go" ,
2329 rust : ".rs" ,
30+ bash : ".sh" ,
2431} ;
2532
26- function detectLanguage ( filePath : string ) : string | null {
33+ function detectRuntime ( filePath : string ) : SandboxRuntime | null {
2734 const ext = extname ( filePath ) . toLowerCase ( ) ;
28- return EXTENSION_TO_LANGUAGE [ ext ] ?? null ;
35+ return EXTENSION_TO_RUNTIME [ ext ] ?? null ;
2936}
3037
31- function resolveLanguage ( files : string [ ] ) : string {
38+ function resolveRuntime ( files : string [ ] ) : SandboxRuntime {
3239 const entrypoint = files [ 0 ] ;
3340 if ( entrypoint == null ) {
3441 throw new CliError ( "No files specified." ) ;
3542 }
36- const detected = detectLanguage ( entrypoint ) ;
43+ const detected = detectRuntime ( entrypoint ) ;
3744 if ( detected == null ) {
3845 throw new CliError (
39- `Cannot detect language for '${ entrypoint } '. Use --language to specify.` ,
46+ `Cannot detect runtime for '${ entrypoint } '. Use --runtime to specify.` ,
4047 ) ;
4148 }
4249 return detected ;
@@ -55,14 +62,18 @@ function readFiles(files: string[]): { name: string; content: string }[] {
5562 } ) ;
5663}
5764
65+ function decodeBase64 ( encoded : string ) : string {
66+ return Buffer . from ( encoded , "base64" ) . toString ( ) ;
67+ }
68+
5869export function registerRunCommand ( program : Command ) : void {
5970 program
6071 . command ( "run" )
6172 . description ( "Execute source files in the Codize Sandbox" )
6273 . argument ( "[files...]" , "Source files to execute" )
6374 . option (
64- "-l , --language <language >" ,
65- "Language override (auto-detected from extension by default)" ,
75+ "-r , --runtime <runtime >" ,
76+ "Runtime override (auto-detected from extension by default)" ,
6677 )
6778 . option (
6879 "-k, --api-key <key>" ,
@@ -71,15 +82,15 @@ export function registerRunCommand(program: Command): void {
7182 . option ( "--json" , "Output result as JSON instead of plain text" )
7283 . option (
7384 "-e, --eval <code>" ,
74- "Inline code to execute (requires --language , can be specified multiple times)" ,
85+ "Inline code to execute (requires --runtime , can be specified multiple times)" ,
7586 ( val : string , prev : string [ ] ) => [ ...prev , val ] ,
7687 [ ] as string [ ] ,
7788 )
7889 . action (
7990 async (
8091 files : string [ ] ,
8192 options : {
82- language ?: string ;
93+ runtime ?: SandboxRuntime ;
8394 apiKey ?: string ;
8495 json ?: boolean ;
8596 eval : string [ ] ;
@@ -104,31 +115,31 @@ export function registerRunCommand(program: Command): void {
104115 ) ;
105116 }
106117
107- let language : string ;
118+ let runtime : SandboxRuntime ;
108119 let filePayloads : { name : string ; content : string } [ ] ;
109120
110121 if ( options . eval . length > 0 ) {
111- if ( ! options . language ) {
122+ if ( ! options . runtime ) {
112123 throw new CliError (
113- "Option --language is required when using --eval." ,
124+ "Option --runtime is required when using --eval." ,
114125 ) ;
115126 }
116- language = options . language ;
117- const ext = LANGUAGE_TO_EXTENSION [ language ] ?? "" ;
127+ runtime = options . runtime ;
128+ const ext = RUNTIME_TO_EXTENSION [ runtime ] ?? "" ;
118129 filePayloads = options . eval . map ( ( code , i ) => ( {
119130 name : `file${ i } ${ ext } ` ,
120131 content : code ,
121132 } ) ) ;
122133 } else {
123- language = options . language ?? resolveLanguage ( files ) ;
134+ runtime = options . runtime ?? resolveRuntime ( files ) ;
124135 filePayloads = readFiles ( files ) ;
125136 }
126137
127138 const client = new CodizeClient ( { apiKey } ) ;
128- let result : Awaited < ReturnType < typeof client . sandbox . execute > > ;
139+ let result : SandboxExecuteResponse ;
129140 try {
130141 result = await client . sandbox . execute ( {
131- language ,
142+ runtime ,
132143 files : filePayloads ,
133144 } ) ;
134145 } catch ( err ) {
@@ -155,10 +166,10 @@ export function registerRunCommand(program: Command): void {
155166 result . data . compile != null &&
156167 result . data . compile . output !== ""
157168 ) {
158- process . stderr . write ( result . data . compile . output ) ;
169+ process . stderr . write ( decodeBase64 ( result . data . compile . output ) ) ;
159170 }
160171 if ( result . data . run != null ) {
161- process . stdout . write ( result . data . run . output ) ;
172+ process . stdout . write ( decodeBase64 ( result . data . run . output ) ) ;
162173 }
163174 }
164175
@@ -167,9 +178,9 @@ export function registerRunCommand(program: Command): void {
167178 result . data . compile != null &&
168179 result . data . compile . exitCode !== 0
169180 ) {
170- process . exitCode = result . data . compile . exitCode ?? 1 ;
181+ process . exitCode = result . data . compile . exitCode ;
171182 } else if ( result . data . run != null ) {
172- process . exitCode = result . data . run . exitCode ?? 1 ;
183+ process . exitCode = result . data . run . exitCode ;
173184 } else {
174185 process . exitCode = 1 ;
175186 }
0 commit comments