11import * as tablePrinter from 'console-table-printer'
22import * as commander from 'commander'
3- import * as e2b from 'e2b'
3+ import { components } from 'e2b'
44
55import { client , connectionConfig , ensureAPIKey } from 'src/api'
66import { handleE2BRequestError } from '../../utils/errors'
77
88export const listCommand = new commander . Command ( 'list' )
99 . description ( 'list all running sandboxes' )
1010 . alias ( 'ls' )
11- . action ( async ( ) => {
11+ . option (
12+ '-s, --state <state>' ,
13+ 'filter by state, eg. running, stopped' ,
14+ ( value ) => value . split ( ',' )
15+ )
16+ . option (
17+ '-m, --metadata <metadata>' ,
18+ 'filter by metadata, eg. key1=value1' ,
19+ ( value ) => value . replace ( / , / g, '&' )
20+ )
21+ . option (
22+ '-l, --limit <limit>' ,
23+ 'limit the number of sandboxes returned' ,
24+ ( value ) => parseInt ( value )
25+ )
26+ . action ( async ( options ) => {
1227 try {
13- const sandboxes = await listSandboxes ( )
28+ const sandboxes = await listSandboxes ( {
29+ limit : options . limit ,
30+ state : options . state ,
31+ metadata : options . metadata ,
32+ } )
1433
1534 if ( ! sandboxes ?. length ) {
16- console . log ( 'No running sandboxes. ' )
35+ console . log ( 'No sandboxes found ' )
1736 } else {
1837 const table = new tablePrinter . Table ( {
1938 title : 'Running sandboxes' ,
@@ -28,6 +47,7 @@ export const listCommand = new commander.Command('list')
2847 { name : 'alias' , alignment : 'left' , title : 'Alias' } ,
2948 { name : 'startedAt' , alignment : 'left' , title : 'Started at' } ,
3049 { name : 'endAt' , alignment : 'left' , title : 'End at' } ,
50+ { name : 'state' , alignment : 'left' , title : 'State' } ,
3151 { name : 'cpuCount' , alignment : 'left' , title : 'vCPUs' } ,
3252 { name : 'memoryMB' , alignment : 'left' , title : 'RAM MiB' } ,
3353 { name : 'metadata' , alignment : 'left' , title : 'Metadata' } ,
@@ -39,6 +59,8 @@ export const listCommand = new commander.Command('list')
3959 sandboxID : sandbox . sandboxID ,
4060 startedAt : new Date ( sandbox . startedAt ) . toLocaleString ( ) ,
4161 endAt : new Date ( sandbox . endAt ) . toLocaleString ( ) ,
62+ state :
63+ sandbox . state . charAt ( 0 ) . toUpperCase ( ) + sandbox . state . slice ( 1 ) , // capitalize
4264 metadata : JSON . stringify ( sandbox . metadata ) ,
4365 } ) )
4466 . sort (
@@ -81,15 +103,51 @@ export const listCommand = new commander.Command('list')
81103 }
82104 } )
83105
84- export async function listSandboxes ( ) : Promise <
85- e2b . components [ 'schemas' ] [ 'ListedSandbox' ] [ ]
106+ type ListSandboxesOptions = {
107+ limit ?: number
108+ state ?: components [ 'schemas' ] [ 'SandboxState' ] [ ]
109+ metadata ?: string
110+ }
111+
112+ export async function listSandboxes ( {
113+ limit,
114+ state,
115+ metadata,
116+ } : ListSandboxesOptions = { } ) : Promise <
117+ components [ 'schemas' ] [ 'ListedSandbox' ] [ ]
86118> {
87119 ensureAPIKey ( )
88120
89121 const signal = connectionConfig . getSignal ( )
90- const res = await client . api . GET ( '/sandboxes' , { signal } )
91122
92- handleE2BRequestError ( res , 'Error getting running sandboxes' )
123+ let hasNext = true
124+ let nextToken : string | undefined
125+ let remainingLimit : number | undefined = limit
126+
127+ const sandboxes : components [ 'schemas' ] [ 'ListedSandbox' ] [ ] = [ ]
128+
129+ while ( hasNext && ( ! limit || ( remainingLimit && remainingLimit > 0 ) ) ) {
130+ const res = await client . api . GET ( '/v2/sandboxes' , {
131+ params : {
132+ query : {
133+ state,
134+ metadata,
135+ nextToken,
136+ limit : remainingLimit ,
137+ } ,
138+ } ,
139+ signal,
140+ } )
141+
142+ handleE2BRequestError ( res , 'Error getting running sandboxes' )
143+
144+ nextToken = res . response . headers . get ( 'x-next-token' ) || undefined
145+ hasNext = ! ! nextToken
146+ sandboxes . push ( ...res . data )
147+ if ( limit && remainingLimit ) {
148+ remainingLimit -= res . data . length
149+ }
150+ }
93151
94- return res . data
152+ return sandboxes
95153}
0 commit comments