1+ import 'dart:io' ;
2+ import 'dart:typed_data' ;
3+
4+ import 'package:convert/convert.dart' ;
15import 'package:dcli/dcli.dart' ;
26import 'package:hive/hive.dart' ;
37import 'package:http_parser/http_parser.dart' ;
8+ import 'package:lib5/constants.dart' ;
9+ import 'package:lib5/identity.dart' ;
10+ import 'package:lib5/node.dart' ;
11+ import 'package:lib5/registry.dart' ;
412import 'package:path/path.dart' ;
513import 'package:s5_deploy/definitons/logging.dart' ;
614import 'package:s5/s5.dart' ;
715import 'dart:convert' ;
8- import 'dart:io' ;
916import 'package:http/http.dart' as http;
10- import 'package:s5_deploy/functions/filesystem .dart' ;
17+ import 'package:bip39/bip39 .dart' as bip39 ;
1118
1219Future <S5 > initS5 (String nodeURL, String dbPath, String logPath) async {
1320 final nowInMilliseconds = DateTime .now ().millisecondsSinceEpoch;
@@ -28,6 +35,8 @@ Future<S5> initS5(String nodeURL, String dbPath, String logPath) async {
2835 print (
2936 "No like I'm ${red ("serious" )}, write this down. But to each their own." );
3037 }
38+ Box <dynamic > box = await Hive .openBox ('s5_deploy' );
39+ box.put ('seed' , seed);
3140 await s5.recoverIdentityFromSeedPhrase (seed);
3241 await s5.registerOnNewStorageService (
3342 nodeURL,
@@ -36,61 +45,115 @@ Future<S5> initS5(String nodeURL, String dbPath, String logPath) async {
3645 return s5;
3746}
3847
39- // Future<CID> uploadDirectory(
40- // Map<String, Stream<List<int>>> fileStreams,
41- // Map<String, int> lengths,
42- // String name, {
43- // List<String>? tryFiles,
44- // Map<String, String>? errorPages,
45- // required Function lookupMimeType,
46- // }) async {
47- // final params = {
48- // 'name': name,
49- // };
48+ Future <CID > uploadDirectory (
49+ Map <String , Stream <List <int >>> fileStreams,
50+ Map <String , int > lengths,
51+ S5NodeAPIWithIdentity nodewIdentity,
52+ String name, {
53+ List <String >? tryFiles,
54+ Map <String , String >? errorPages,
55+ required Function lookupMimeType,
56+ }) async {
57+ final params = {
58+ 'name' : name,
59+ };
60+
61+ if (tryFiles != null ) {
62+ params['tryfiles' ] = json.encode (tryFiles);
63+ }
64+ if (errorPages != null ) {
65+ params['errorpages' ] = json.encode (errorPages);
66+ }
67+
68+ final uc = nodewIdentity.accountConfigs.values.first;
69+
70+ var uri = uc.getAPIUrl ('/s5/upload/directory' ).replace (
71+ queryParameters: params,
72+ );
73+
74+ var request = http.MultipartRequest ("POST" , uri);
75+
76+ request.headers.addAll (uc.headers);
77+
78+ for (final filename in fileStreams.keys) {
79+ var stream = http.ByteStream (fileStreams[filename]! );
5080
51- // if (tryFiles != null) {
52- // params['tryfiles'] = json.encode(tryFiles);
53- // }
54- // if (errorPages != null) {
55- // params['errorpages'] = json.encode(errorPages);
56- // }
81+ final mimeType = lookupMimeType (filename);
5782
58- // final uc = storageServiceConfigs.first;
83+ var multipartFile = http.MultipartFile (
84+ filename,
85+ stream,
86+ lengths[filename]! ,
87+ filename: filename,
88+ contentType: mimeType == null ? null : MediaType .parse (mimeType),
89+ );
5990
60- // var uri = uc.getAPIUrl('/s5/upload/directory').replace(
61- // queryParameters: params,
62- // );
91+ request.files.add (multipartFile);
92+ }
6393
64- // var request = http.MultipartRequest("POST", uri );
94+ final response = await request. send ( );
6595
66- // request.headers.addAll(uc.headers);
96+ if (response.statusCode != 200 ) {
97+ throw Exception ('HTTP ${response .statusCode }' );
98+ }
6799
68- // for (final filename in fileStreams.keys) {
69- // var stream = http.ByteStream(fileStreams[filename]!);
100+ final res = await response.stream.transform (utf8.decoder).join ();
70101
71- // final mimeType = lookupMimeType(filename);
102+ final resData = json.decode (res);
103+
104+ if (resData['cid' ] == null ) throw Exception ('Directory upload failed' );
105+ return CID .decode (resData['cid' ]);
106+ }
72107
73- // var multipartFile = http.MultipartFile(
74- // filename,
75- // stream,
76- // lengths[filename]!,
77- // filename: filename,
78- // contentType: mimeType == null ? null : MediaType.parse(mimeType),
79- // );
108+ Future <CID > updateResolver (S5 s5, String dir, CID staticCID) async {
109+ Box <dynamic > box = await Hive .openBox ('s5_deploy' );
110+ String seed = box.get ('seed' );
111+ String dataKey = "" ;
112+ try {
113+ dataKey = box.get ('datakey' );
114+ } catch (_) {
115+ dataKey = 'project-${Directory (dir ).absolute .path }' ;
116+ }
80117
81- // request.files.add(multipartFile);
82- // }
118+ final resolverSeed = s5.api.crypto.hashBlake3Sync (
119+ Uint8List .fromList (
120+ validatePhrase (seed, crypto: s5.api.crypto) + utf8.encode (dataKey),
121+ ),
122+ );
83123
84- // final response = await HttpClient.send(request );
124+ final s5User = await s5.api.crypto. newKeyPairEd25519 (seed : resolverSeed );
85125
86- // if (response.statusCode != 200) {
87- // throw Exception('HTTP ${response.statusCode}');
88- // }
126+ SignedRegistryEntry ? existing;
89127
90- // final res = await response.stream.transform(utf8.decoder).join();
128+ try {
129+ final res = await s5.api.registryGet (s5User.publicKey);
130+ existing = res;
131+ if (existing != null ) {
132+ print (
133+ 'Revision ${existing .revision } -> ${existing .revision + 1 }' ,
134+ );
135+ }
136+ } catch (e) {
137+ existing = null ;
91138
92- // final resData = json.decode(res);
139+ print ('Revision 1' );
140+ }
93141
94- // if (resData['cid'] == null) throw Exception('Directory upload failed');
95- // return CID.decode(resData['cid']);
96- // }
142+ final sre = await signRegistryEntry (
143+ kp: s5User,
144+ data: staticCID.toRegistryEntry (),
145+ revision: (existing? .revision ?? - 1 ) + 1 ,
146+ crypto: s5.api.crypto,
147+ );
148+
149+ await s5.api.registrySet (sre);
150+
151+ final resolverCID = CID (
152+ cidTypeResolver,
153+ Multihash (
154+ Uint8List .fromList (
155+ s5User.publicKey,
156+ ),
157+ ));
158+ return resolverCID;
159+ }
0 commit comments