1- use std:: io;
2-
31use crate :: common_args;
42use crate :: config:: Config ;
5- use crate :: util:: { add_auth_header_opt, database_identity, get_auth_header, y_or_n , AuthHeader } ;
3+ use crate :: util:: { add_auth_header_opt, database_identity, get_auth_header} ;
64use clap:: { Arg , ArgMatches } ;
7- use http:: StatusCode ;
8- use itertools:: Itertools as _;
9- use reqwest:: Response ;
10- use spacetimedb_client_api_messages:: http:: { DatabaseDeleteConfirmationResponse , DatabaseTree , DatabaseTreeNode } ;
11- use spacetimedb_lib:: Hash ;
12- use tokio:: io:: AsyncWriteExt as _;
135
146pub fn cli ( ) -> clap:: Command {
157 clap:: Command :: new ( "delete" )
@@ -30,143 +22,11 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E
3022 let force = args. get_flag ( "force" ) ;
3123
3224 let identity = database_identity ( & config, database, server) . await ?;
33- let host_url = config. get_host_url ( server) ?;
34- let request_path = format ! ( "{host_url}/v1/database/{identity}" ) ;
35- let auth_header = get_auth_header ( & mut config, false , server, !force) . await ?;
36- let client = reqwest:: Client :: new ( ) ;
37-
38- let response = send_request ( & client, & request_path, & auth_header, None ) . await ?;
39- match response. status ( ) {
40- StatusCode :: PRECONDITION_REQUIRED => {
41- let confirm = response. json :: < DatabaseDeleteConfirmationResponse > ( ) . await ?;
42- println ! ( "WARNING: Deleting the database {identity} will also delete its children!" ) ;
43- if !force {
44- print_database_tree_info ( & confirm. database_tree ) . await ?;
45- }
46- if y_or_n ( force, "Do you want to proceed deleting above databases?" ) ? {
47- send_request ( & client, & request_path, & auth_header, Some ( confirm. confirmation_token ) )
48- . await ?
49- . error_for_status ( ) ?;
50- } else {
51- println ! ( "Aborting" ) ;
52- }
53-
54- Ok ( ( ) )
55- }
56- StatusCode :: OK => Ok ( ( ) ) ,
57- _ => response. error_for_status ( ) . map ( drop) . map_err ( Into :: into) ,
58- }
59- }
60-
61- async fn send_request (
62- client : & reqwest:: Client ,
63- request_path : & str ,
64- auth : & AuthHeader ,
65- confirmation_token : Option < Hash > ,
66- ) -> Result < Response , reqwest:: Error > {
67- let mut builder = client. delete ( request_path) ;
68- builder = add_auth_header_opt ( builder, auth) ;
69- if let Some ( token) = confirmation_token {
70- builder = builder. query ( & [ ( "token" , token) ] ) ;
71- }
72- builder. send ( ) . await
73- }
74-
75- async fn print_database_tree_info ( tree : & DatabaseTree ) -> io:: Result < ( ) > {
76- tokio:: io:: stdout ( )
77- . write_all ( as_termtree ( tree) . to_string ( ) . as_bytes ( ) )
78- . await
79- }
8025
81- fn as_termtree ( tree : & DatabaseTree ) -> termtree:: Tree < String > {
82- let mut stack: Vec < ( & DatabaseTree , bool ) > = vec ! [ ] ;
83- stack. push ( ( tree, false ) ) ;
84-
85- let mut built: Vec < termtree:: Tree < String > > = <_ >:: default ( ) ;
86-
87- while let Some ( ( node, visited) ) = stack. pop ( ) {
88- if visited {
89- let mut term_node = termtree:: Tree :: new ( fmt_tree_node ( & node. root ) ) ;
90- term_node. leaves = built. drain ( built. len ( ) - node. children . len ( ) ..) . collect ( ) ;
91- term_node. leaves . reverse ( ) ;
92- built. push ( term_node) ;
93- } else {
94- stack. push ( ( node, true ) ) ;
95- stack. extend ( node. children . iter ( ) . rev ( ) . map ( |child| ( child, false ) ) ) ;
96- }
97- }
98-
99- built
100- . pop ( )
101- . expect ( "database tree contains a root and we pushed it last" )
102- }
103-
104- fn fmt_tree_node ( node : & DatabaseTreeNode ) -> String {
105- format ! (
106- "{}{}" ,
107- node. database_identity,
108- if node. database_names. is_empty( ) {
109- <_>:: default ( )
110- } else {
111- format!( ": {}" , node. database_names. iter( ) . join( ", " ) )
112- }
113- )
114- }
115-
116- #[ cfg( test) ]
117- mod tests {
118- use super :: * ;
119- use spacetimedb_client_api_messages:: http:: { DatabaseTree , DatabaseTreeNode } ;
120- use spacetimedb_lib:: { sats:: u256, Identity } ;
26+ let builder = reqwest:: Client :: new ( ) . delete ( format ! ( "{}/v1/database/{}" , config. get_host_url( server) ?, identity) ) ;
27+ let auth_header = get_auth_header ( & mut config, false , server, !force) . await ?;
28+ let builder = add_auth_header_opt ( builder, & auth_header) ;
29+ builder. send ( ) . await ?. error_for_status ( ) ?;
12130
122- #[ test]
123- fn render_termtree ( ) {
124- let tree = DatabaseTree {
125- root : DatabaseTreeNode {
126- database_identity : Identity :: ONE ,
127- database_names : [ "parent" . into ( ) ] . into ( ) ,
128- } ,
129- children : vec ! [
130- DatabaseTree {
131- root: DatabaseTreeNode {
132- database_identity: Identity :: from_u256( u256:: new( 2 ) ) ,
133- database_names: [ "child" . into( ) ] . into( ) ,
134- } ,
135- children: vec![
136- DatabaseTree {
137- root: DatabaseTreeNode {
138- database_identity: Identity :: from_u256( u256:: new( 3 ) ) ,
139- database_names: [ "grandchild" . into( ) ] . into( ) ,
140- } ,
141- children: vec![ ] ,
142- } ,
143- DatabaseTree {
144- root: DatabaseTreeNode {
145- database_identity: Identity :: from_u256( u256:: new( 5 ) ) ,
146- database_names: [ ] . into( ) ,
147- } ,
148- children: vec![ ] ,
149- } ,
150- ] ,
151- } ,
152- DatabaseTree {
153- root: DatabaseTreeNode {
154- database_identity: Identity :: from_u256( u256:: new( 4 ) ) ,
155- database_names: [ "sibling" . into( ) , "bro" . into( ) ] . into( ) ,
156- } ,
157- children: vec![ ] ,
158- } ,
159- ] ,
160- } ;
161- pretty_assertions:: assert_eq!(
162- "\
163- 0000000000000000000000000000000000000000000000000000000000000001: parent
164- ├── 0000000000000000000000000000000000000000000000000000000000000004: bro, sibling
165- └── 0000000000000000000000000000000000000000000000000000000000000002: child
166- ├── 0000000000000000000000000000000000000000000000000000000000000005
167- └── 0000000000000000000000000000000000000000000000000000000000000003: grandchild
168- " ,
169- & as_termtree( & tree) . to_string( )
170- ) ;
171- }
31+ Ok ( ( ) )
17232}
0 commit comments