+33
-36
crates/jacquard-common/src/xrpc.rs
+33
-36
crates/jacquard-common/src/xrpc.rs
···
232
232
233
233
impl<T: HttpClient> XrpcExt for T {}
234
234
235
+
/// Nicer alias for Xrpc response type
236
+
pub type XrpcResponse<R> = Response<<R as XrpcRequest>::Response>;
237
+
235
238
/// Stateful XRPC call trait
236
239
#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(Send))]
237
240
pub trait XrpcClient: HttpClient {
···
245
248
246
249
/// Send an XRPC request and parse the response
247
250
#[cfg(not(target_arch = "wasm32"))]
248
-
fn send<R>(
249
-
&self,
250
-
request: R,
251
-
) -> impl Future<Output = XrpcResult<Response<<R as XrpcRequest>::Response>>>
251
+
fn send<R>(&self, request: R) -> impl Future<Output = XrpcResult<XrpcResponse<R>>>
252
252
where
253
253
R: XrpcRequest + Send + Sync,
254
254
<R as XrpcRequest>::Response: Send + Sync,
···
256
256
257
257
/// Send an XRPC request and parse the response
258
258
#[cfg(target_arch = "wasm32")]
259
-
fn send<R>(
260
-
&self,
261
-
request: R,
262
-
) -> impl Future<Output = XrpcResult<Response<<R as XrpcRequest>::Response>>>
259
+
fn send<R>(&self, request: R) -> impl Future<Output = XrpcResult<XrpcResponse<R>>>
263
260
where
264
261
R: XrpcRequest + Send + Sync,
265
262
<R as XrpcRequest>::Response: Send + Sync;
···
270
267
&self,
271
268
request: R,
272
269
opts: CallOptions<'_>,
273
-
) -> impl Future<Output = XrpcResult<Response<<R as XrpcRequest>::Response>>>
270
+
) -> impl Future<Output = XrpcResult<XrpcResponse<R>>>
274
271
where
275
272
R: XrpcRequest + Send + Sync,
276
273
<R as XrpcRequest>::Response: Send + Sync,
···
282
279
&self,
283
280
request: R,
284
281
opts: CallOptions<'_>,
285
-
) -> impl Future<Output = XrpcResult<Response<<R as XrpcRequest>::Response>>>
282
+
) -> impl Future<Output = XrpcResult<XrpcResponse<R>>>
286
283
where
287
284
R: XrpcRequest + Send + Sync,
288
285
<R as XrpcRequest>::Response: Send + Sync;
···
517
514
status: StatusCode,
518
515
}
519
516
520
-
impl<Resp> Response<Resp>
517
+
impl<R> Response<R>
521
518
where
522
-
Resp: XrpcResp,
519
+
R: XrpcResp,
523
520
{
524
521
/// Create a new response from a buffer and status code
525
522
pub fn new(buffer: Bytes, status: StatusCode) -> Self {
···
541
538
}
542
539
543
540
/// Parse the response, borrowing from the internal buffer
544
-
pub fn parse<'s>(
545
-
&'s self,
546
-
) -> Result<<Resp as XrpcResp>::Output<'s>, XrpcError<<Resp as XrpcResp>::Err<'s>>> {
541
+
pub fn parse<'s>(&'s self) -> Result<RespOutput<'s, R>, XrpcError<RespErr<'s, R>>> {
547
542
// 200: parse as output
548
543
if self.status.is_success() {
549
544
match serde_json::from_slice::<_>(&self.buffer) {
···
558
553
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
559
554
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
560
555
Ok(mut generic) => {
561
-
generic.nsid = Resp::NSID;
556
+
generic.nsid = R::NSID;
562
557
generic.method = ""; // method info only available on request
563
558
generic.http_status = self.status;
564
559
// Map auth-related errors to AuthError
···
576
571
} else {
577
572
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
578
573
Ok(mut generic) => {
579
-
generic.nsid = Resp::NSID;
574
+
generic.nsid = R::NSID;
580
575
generic.method = ""; // method info only available on request
581
576
generic.http_status = self.status;
582
577
match generic.error.as_str() {
···
593
588
/// Parse this as validated, loosely typed atproto data.
594
589
///
595
590
/// NOTE: If the response is an error, it will still parse as the matching error type for the request.
596
-
pub fn parse_data<'s>(&'s self) -> Result<Data<'s>, XrpcError<<Resp as XrpcResp>::Err<'s>>> {
591
+
pub fn parse_data<'s>(&'s self) -> Result<Data<'s>, XrpcError<RespErr<'s, R>>> {
597
592
// 200: parse as output
598
593
if self.status.is_success() {
599
594
match serde_json::from_slice::<_>(&self.buffer) {
···
608
603
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
609
604
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
610
605
Ok(mut generic) => {
611
-
generic.nsid = Resp::NSID;
606
+
generic.nsid = R::NSID;
612
607
generic.method = ""; // method info only available on request
613
608
generic.http_status = self.status;
614
609
// Map auth-related errors to AuthError
···
626
621
} else {
627
622
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
628
623
Ok(mut generic) => {
629
-
generic.nsid = Resp::NSID;
624
+
generic.nsid = R::NSID;
630
625
generic.method = ""; // method info only available on request
631
626
generic.http_status = self.status;
632
627
match generic.error.as_str() {
···
643
638
/// Parse this as raw atproto data with minimal validation.
644
639
///
645
640
/// NOTE: If the response is an error, it will still parse as the matching error type for the request.
646
-
pub fn parse_raw<'s>(&'s self) -> Result<RawData<'s>, XrpcError<<Resp as XrpcResp>::Err<'s>>> {
641
+
pub fn parse_raw<'s>(&'s self) -> Result<RawData<'s>, XrpcError<RespErr<'s, R>>> {
647
642
// 200: parse as output
648
643
if self.status.is_success() {
649
644
match serde_json::from_slice::<_>(&self.buffer) {
···
658
653
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
659
654
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
660
655
Ok(mut generic) => {
661
-
generic.nsid = Resp::NSID;
656
+
generic.nsid = R::NSID;
662
657
generic.method = ""; // method info only available on request
663
658
generic.http_status = self.status;
664
659
// Map auth-related errors to AuthError
···
676
671
} else {
677
672
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
678
673
Ok(mut generic) => {
679
-
generic.nsid = Resp::NSID;
674
+
generic.nsid = R::NSID;
680
675
generic.method = ""; // method info only available on request
681
676
generic.http_status = self.status;
682
677
match generic.error.as_str() {
···
710
705
}
711
706
}
712
707
713
-
impl<Resp> Response<Resp>
708
+
/// doc
709
+
pub type RespOutput<'a, Resp> = <Resp as XrpcResp>::Output<'a>;
710
+
/// doc
711
+
pub type RespErr<'a, Resp> = <Resp as XrpcResp>::Err<'a>;
712
+
713
+
impl<R> Response<R>
714
714
where
715
-
Resp: XrpcResp,
715
+
R: XrpcResp,
716
716
{
717
717
/// Parse the response into an owned output
718
-
pub fn into_output(
719
-
self,
720
-
) -> Result<<Resp as XrpcResp>::Output<'static>, XrpcError<<Resp as XrpcResp>::Err<'static>>>
718
+
pub fn into_output(self) -> Result<RespOutput<'static, R>, XrpcError<RespErr<'static, R>>>
721
719
where
722
-
for<'a> <Resp as XrpcResp>::Output<'a>:
723
-
IntoStatic<Output = <Resp as XrpcResp>::Output<'static>>,
724
-
for<'a> <Resp as XrpcResp>::Err<'a>: IntoStatic<Output = <Resp as XrpcResp>::Err<'static>>,
720
+
for<'a> RespOutput<'a, R>: IntoStatic<Output = RespOutput<'static, R>>,
721
+
for<'a> RespErr<'a, R>: IntoStatic<Output = RespErr<'static, R>>,
725
722
{
726
723
// Use a helper to make lifetime inference work
727
724
fn parse_output<'b, R: XrpcResp>(
···
736
733
737
734
// 200: parse as output
738
735
if self.status.is_success() {
739
-
match parse_output::<Resp>(&self.buffer) {
736
+
match parse_output::<R>(&self.buffer) {
740
737
Ok(output) => {
741
738
return Ok(output.into_static());
742
739
}
···
744
741
}
745
742
// 400: try typed XRPC error, fallback to generic error
746
743
} else if self.status.as_u16() == 400 {
747
-
let error = match parse_error::<Resp>(&self.buffer) {
744
+
let error = match parse_error::<R>(&self.buffer) {
748
745
Ok(error) => XrpcError::Xrpc(error),
749
746
Err(_) => {
750
747
// Fallback to generic error (InvalidRequest, ExpiredToken, etc.)
751
748
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
752
749
Ok(mut generic) => {
753
-
generic.nsid = Resp::NSID;
750
+
generic.nsid = R::NSID;
754
751
generic.method = ""; // method info only available on request
755
752
generic.http_status = self.status;
756
753
// Map auth-related errors to AuthError
···
767
764
Err(error.into_static())
768
765
// 401: always auth error
769
766
} else {
770
-
let error: XrpcError<<Resp as XrpcResp>::Err<'_>> =
767
+
let error: XrpcError<<R as XrpcResp>::Err<'_>> =
771
768
match serde_json::from_slice::<GenericXrpcError>(&self.buffer) {
772
769
Ok(mut generic) => {
773
770
let status = self.status;
774
-
generic.nsid = Resp::NSID;
771
+
generic.nsid = R::NSID;
775
772
generic.method = ""; // method info only available on request
776
773
generic.http_status = status;
777
774
match generic.error.as_ref() {
+12
-16
crates/jacquard-oauth/src/client.rs
+12
-16
crates/jacquard-oauth/src/client.rs
···
15
15
http_client::HttpClient,
16
16
types::{did::Did, string::Handle},
17
17
xrpc::{
18
-
CallOptions, Response, XrpcClient, XrpcExt, XrpcRequest, XrpcResp, build_http_request,
19
-
process_response,
18
+
CallOptions, Response, XrpcClient, XrpcError, XrpcExt, XrpcRequest, XrpcResp, XrpcResponse,
19
+
build_http_request, process_response,
20
20
},
21
21
};
22
-
use jacquard_identity::{JacquardResolver, resolver::IdentityResolver};
22
+
use jacquard_identity::{
23
+
JacquardResolver,
24
+
resolver::{DidDocResponse, IdentityError, IdentityResolver, ResolverOptions},
25
+
};
23
26
use jose_jwk::JwkSet;
24
27
use std::sync::Arc;
25
28
use tokio::sync::RwLock;
···
434
437
self.options.read().await.clone()
435
438
}
436
439
437
-
async fn send<R>(&self, request: R) -> XrpcResult<Response<<R as XrpcRequest>::Response>>
440
+
async fn send<R>(&self, request: R) -> XrpcResult<XrpcResponse<R>>
438
441
where
439
442
R: XrpcRequest + Send + Sync,
440
443
<R as XrpcRequest>::Response: Send + Sync,
···
447
450
&self,
448
451
request: R,
449
452
mut opts: CallOptions<'_>,
450
-
) -> XrpcResult<Response<<R as XrpcRequest>::Response>>
453
+
) -> XrpcResult<XrpcResponse<R>>
451
454
where
452
455
R: XrpcRequest + Send + Sync,
453
456
<R as XrpcRequest>::Response: Send + Sync,
···
492
495
.to_str()
493
496
.is_ok_and(|s| s.starts_with("DPoP ") && s.contains("error=\"invalid_token\"")),
494
497
Ok(resp) => match resp.parse() {
495
-
Err(jacquard_common::xrpc::XrpcError::Auth(AuthError::InvalidToken)) => true,
498
+
Err(XrpcError::Auth(AuthError::InvalidToken)) => true,
496
499
_ => false,
497
500
},
498
501
_ => false,
···
504
507
S: ClientAuthStore + Send + Sync + 'static,
505
508
T: OAuthResolver + IdentityResolver + XrpcExt + Send + Sync + 'static,
506
509
{
507
-
fn options(&self) -> &jacquard_identity::resolver::ResolverOptions {
510
+
fn options(&self) -> &ResolverOptions {
508
511
self.client.options()
509
512
}
510
513
511
514
fn resolve_handle(
512
515
&self,
513
516
handle: &Handle<'_>,
514
-
) -> impl Future<
515
-
Output = std::result::Result<Did<'static>, jacquard_identity::resolver::IdentityError>,
516
-
> {
517
+
) -> impl Future<Output = std::result::Result<Did<'static>, IdentityError>> {
517
518
async { self.client.resolve_handle(handle).await }
518
519
}
519
520
520
521
fn resolve_did_doc(
521
522
&self,
522
523
did: &Did<'_>,
523
-
) -> impl Future<
524
-
Output = std::result::Result<
525
-
jacquard_identity::resolver::DidDocResponse,
526
-
jacquard_identity::resolver::IdentityError,
527
-
>,
528
-
> {
524
+
) -> impl Future<Output = std::result::Result<DidDocResponse, IdentityError>> {
529
525
async { self.client.resolve_did_doc(did).await }
530
526
}
531
527
}
+14
-3
crates/jacquard-oauth/src/dpop.rs
+14
-3
crates/jacquard-oauth/src/dpop.rs
···
1
+
use std::future::Future;
2
+
1
3
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
2
4
use chrono::Utc;
3
5
use http::{Request, Response, header::InvalidHeaderValue};
···
43
45
44
46
#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(Send))]
45
47
pub trait DpopClient: HttpClient {
46
-
fn dpop_server(&self, request: Request<Vec<u8>>) -> impl std::future::Future<Output = Result<Response<Vec<u8>>>>;
47
-
fn dpop_client(&self, request: Request<Vec<u8>>) -> impl std::future::Future<Output = Result<Response<Vec<u8>>>>;
48
-
fn wrap_request(&self, request: Request<Vec<u8>>) -> impl std::future::Future<Output = Result<Response<Vec<u8>>>>;
48
+
fn dpop_server(
49
+
&self,
50
+
request: Request<Vec<u8>>,
51
+
) -> impl Future<Output = Result<Response<Vec<u8>>>>;
52
+
fn dpop_client(
53
+
&self,
54
+
request: Request<Vec<u8>>,
55
+
) -> impl Future<Output = Result<Response<Vec<u8>>>>;
56
+
fn wrap_request(
57
+
&self,
58
+
request: Request<Vec<u8>>,
59
+
) -> impl Future<Output = Result<Response<Vec<u8>>>>;
49
60
}
50
61
51
62
pub trait DpopExt: HttpClient {
+26
-29
crates/jacquard-oauth/src/resolver.rs
+26
-29
crates/jacquard-oauth/src/resolver.rs
···
1
+
#[cfg(not(target_arch = "wasm32"))]
2
+
use std::future::Future;
3
+
1
4
use crate::types::{OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata};
2
5
use http::{Request, StatusCode};
3
6
use jacquard_common::CowStr;
···
400
403
&self,
401
404
server_metadata: &OAuthAuthorizationServerMetadata<'_>,
402
405
sub: &Did<'_>,
403
-
) -> impl std::future::Future<Output = Result<Url, ResolverError>> + Send
406
+
) -> impl Future<Output = Result<Url, ResolverError>> + Send
404
407
where
405
408
Self: Sync,
406
409
{
···
412
415
&self,
413
416
server_metadata: &OAuthAuthorizationServerMetadata<'_>,
414
417
sub: &Did<'_>,
415
-
) -> impl std::future::Future<Output = Result<Url, ResolverError>> {
418
+
) -> impl Future<Output = Result<Url, ResolverError>> {
416
419
verify_issuer_impl(self, server_metadata, sub)
417
420
}
418
421
···
420
423
fn resolve_oauth(
421
424
&self,
422
425
input: &str,
423
-
) -> impl std::future::Future<
426
+
) -> impl Future<
424
427
Output = Result<
425
428
(
426
429
OAuthAuthorizationServerMetadata<'static>,
···
439
442
fn resolve_oauth(
440
443
&self,
441
444
input: &str,
442
-
) -> impl std::future::Future<
445
+
) -> impl Future<
443
446
Output = Result<
444
447
(
445
448
OAuthAuthorizationServerMetadata<'static>,
···
455
458
fn resolve_from_service(
456
459
&self,
457
460
input: &Url,
458
-
) -> impl std::future::Future<
459
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
460
-
> + Send
461
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>> + Send
461
462
where
462
463
Self: Sync,
463
464
{
···
468
469
fn resolve_from_service(
469
470
&self,
470
471
input: &Url,
471
-
) -> impl std::future::Future<
472
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
473
-
> {
472
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>>
473
+
{
474
474
resolve_from_service_impl(self, input)
475
475
}
476
476
···
478
478
fn resolve_from_identity(
479
479
&self,
480
480
input: &str,
481
-
) -> impl std::future::Future<
481
+
) -> impl Future<
482
482
Output = Result<
483
483
(
484
484
OAuthAuthorizationServerMetadata<'static>,
···
497
497
fn resolve_from_identity(
498
498
&self,
499
499
input: &str,
500
-
) -> impl std::future::Future<
500
+
) -> impl Future<
501
501
Output = Result<
502
502
(
503
503
OAuthAuthorizationServerMetadata<'static>,
···
513
513
fn get_authorization_server_metadata(
514
514
&self,
515
515
issuer: &Url,
516
-
) -> impl std::future::Future<
517
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
518
-
> + Send
516
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>> + Send
519
517
where
520
518
Self: Sync,
521
519
{
···
526
524
fn get_authorization_server_metadata(
527
525
&self,
528
526
issuer: &Url,
529
-
) -> impl std::future::Future<
530
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
531
-
> {
527
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>>
528
+
{
532
529
get_authorization_server_metadata_impl(self, issuer)
533
530
}
534
531
···
536
533
fn get_resource_server_metadata(
537
534
&self,
538
535
pds: &Url,
539
-
) -> impl std::future::Future<
540
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
541
-
> + Send
536
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>> + Send
542
537
where
543
538
Self: Sync,
544
539
{
···
549
544
fn get_resource_server_metadata(
550
545
&self,
551
546
pds: &Url,
552
-
) -> impl std::future::Future<
553
-
Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>,
554
-
> {
547
+
) -> impl Future<Output = Result<OAuthAuthorizationServerMetadata<'static>, ResolverError>>
548
+
{
555
549
get_resource_server_metadata_impl(self, pds)
556
550
}
557
551
}
···
630
624
631
625
#[cfg(test)]
632
626
mod tests {
627
+
use core::future::Future;
628
+
use std::{convert::Infallible, sync::Arc};
629
+
633
630
use super::*;
634
631
use http::{Request as HttpRequest, Response as HttpResponse, StatusCode};
635
632
use jacquard_common::http_client::HttpClient;
633
+
use tokio::sync::Mutex;
636
634
637
635
#[derive(Default, Clone)]
638
636
struct MockHttp {
639
-
next: std::sync::Arc<tokio::sync::Mutex<Option<HttpResponse<Vec<u8>>>>>,
637
+
next: Arc<Mutex<Option<HttpResponse<Vec<u8>>>>>,
640
638
}
641
639
642
640
impl HttpClient for MockHttp {
643
-
type Error = std::convert::Infallible;
641
+
type Error = Infallible;
644
642
fn send_http(
645
643
&self,
646
644
_request: HttpRequest<Vec<u8>>,
647
-
) -> impl core::future::Future<
648
-
Output = core::result::Result<HttpResponse<Vec<u8>>, Self::Error>,
649
-
> + Send {
645
+
) -> impl Future<Output = core::result::Result<HttpResponse<Vec<u8>>, Self::Error>> + Send
646
+
{
650
647
let next = self.next.clone();
651
648
async move { Ok(next.lock().await.take().unwrap()) }
652
649
}
+31
-40
crates/jacquard/src/client.rs
+31
-40
crates/jacquard/src/client.rs
···
40
40
CowStr, IntoStatic,
41
41
types::string::{Did, Handle},
42
42
};
43
-
use jacquard_identity::resolver::IdentityResolver;
43
+
use jacquard_identity::resolver::{
44
+
DidDocResponse, IdentityError, IdentityResolver, ResolverOptions,
45
+
};
44
46
use jacquard_oauth::authstore::ClientAuthStore;
45
47
use jacquard_oauth::client::OAuthSession;
46
48
use jacquard_oauth::dpop::DpopExt;
···
325
327
server::{create_session::CreateSessionOutput, refresh_session::RefreshSessionOutput},
326
328
};
327
329
330
+
/// doc
331
+
pub type CollectionOutput<'a, R> = <<R as Collection>::Record as XrpcResp>::Output<'a>;
332
+
/// doc
333
+
pub type CollectionErr<'a, R> = <<R as Collection>::Record as XrpcResp>::Err<'a>;
334
+
/// doc
335
+
pub type VecGetResponse<U> = <<U as VecUpdate>::GetRequest as XrpcRequest>::Response;
336
+
/// doc
337
+
pub type VecPutResponse<U> = <<U as VecUpdate>::PutRequest as XrpcRequest>::Response;
338
+
328
339
/// Extension trait providing convenience methods for common repository operations.
329
340
///
330
341
/// This trait is automatically implemented for any type that implements both
···
406
417
&self,
407
418
record: R,
408
419
rkey: Option<RecordKey<Rkey<'_>>>,
409
-
) -> impl std::future::Future<Output = Result<CreateRecordOutput<'static>, AgentError>>
420
+
) -> impl Future<Output = Result<CreateRecordOutput<'static>, AgentError>>
410
421
where
411
422
R: Collection + serde::Serialize,
412
423
{
···
474
485
fn get_record<R>(
475
486
&self,
476
487
uri: AtUri<'_>,
477
-
) -> impl std::future::Future<Output = Result<Response<R::Record>, ClientError>>
488
+
) -> impl Future<Output = Result<Response<R::Record>, ClientError>>
478
489
where
479
490
R: Collection,
480
491
{
···
550
561
&self,
551
562
record_type: R,
552
563
uri: AtUri<'_>,
553
-
) -> impl std::future::Future<
554
-
Output = Result<<<R as Collection>::Record as XrpcResp>::Output<'static>, ClientError>,
555
-
>
564
+
) -> impl Future<Output = Result<CollectionOutput<'static, R>, ClientError>>
556
565
where
557
566
R: Collection,
558
-
for<'a> <<R as Collection>::Record as XrpcResp>::Output<'a>:
559
-
IntoStatic<Output = <<R as Collection>::Record as XrpcResp>::Output<'static>>,
560
-
for<'a> <<R as Collection>::Record as XrpcResp>::Err<'a>:
561
-
IntoStatic<Output = <<R as Collection>::Record as XrpcResp>::Err<'static>>,
567
+
for<'a> CollectionOutput<'a, R>: IntoStatic<Output = CollectionOutput<'static, R>>,
568
+
for<'a> CollectionErr<'a, R>: IntoStatic<Output = CollectionErr<'static, R>>,
562
569
{
563
570
let _ = record_type;
564
571
async move {
···
602
609
&self,
603
610
uri: AtUri<'_>,
604
611
f: impl FnOnce(&mut R),
605
-
) -> impl std::future::Future<Output = Result<PutRecordOutput<'static>, AgentError>>
612
+
) -> impl Future<Output = Result<PutRecordOutput<'static>, AgentError>>
606
613
where
607
614
R: Collection + Serialize,
608
-
R: for<'a> From<<<R as Collection>::Record as XrpcResp>::Output<'a>>,
615
+
R: for<'a> From<CollectionOutput<'a, R>>,
609
616
{
610
617
async move {
611
618
#[cfg(feature = "tracing")]
···
652
659
fn delete_record<R>(
653
660
&self,
654
661
rkey: RecordKey<Rkey<'_>>,
655
-
) -> impl std::future::Future<Output = Result<DeleteRecordOutput<'static>, AgentError>>
662
+
) -> impl Future<Output = Result<DeleteRecordOutput<'static>, AgentError>>
656
663
where
657
664
R: Collection,
658
665
{
···
692
699
&self,
693
700
rkey: RecordKey<Rkey<'static>>,
694
701
record: R,
695
-
) -> impl std::future::Future<Output = Result<PutRecordOutput<'static>, AgentError>>
702
+
) -> impl Future<Output = Result<PutRecordOutput<'static>, AgentError>>
696
703
where
697
704
R: Collection + serde::Serialize,
698
705
{
···
755
762
&self,
756
763
data: impl Into<bytes::Bytes>,
757
764
mime_type: MimeType<'_>,
758
-
) -> impl std::future::Future<Output = Result<Blob<'static>, AgentError>> {
765
+
) -> impl Future<Output = Result<Blob<'static>, AgentError>> {
759
766
async move {
760
767
#[cfg(feature = "tracing")]
761
768
let _span = tracing::debug_span!("upload_blob", mime_type = %mime_type).entered();
···
808
815
fn update_vec<U>(
809
816
&self,
810
817
modify: impl FnOnce(&mut Vec<<U as VecUpdate>::Item>),
811
-
) -> impl std::future::Future<
812
-
Output = Result<
813
-
xrpc::Response<<<U as VecUpdate>::PutRequest as XrpcRequest>::Response>,
814
-
AgentError,
815
-
>,
816
-
>
818
+
) -> impl Future<Output = Result<xrpc::Response<VecPutResponse<U>>, AgentError>>
817
819
where
818
820
U: VecUpdate,
819
821
<U as VecUpdate>::PutRequest: Send + Sync,
820
822
<U as VecUpdate>::GetRequest: Send + Sync,
821
-
<<U as VecUpdate>::GetRequest as XrpcRequest>::Response: Send + Sync,
822
-
<<U as VecUpdate>::PutRequest as XrpcRequest>::Response: Send + Sync,
823
+
VecGetResponse<U>: Send + Sync,
824
+
VecPutResponse<U>: Send + Sync,
823
825
{
824
826
async {
825
827
// Fetch current data
···
863
865
fn update_vec_item<U>(
864
866
&self,
865
867
item: <U as VecUpdate>::Item,
866
-
) -> impl std::future::Future<
867
-
Output = Result<
868
-
xrpc::Response<<<U as VecUpdate>::PutRequest as XrpcRequest>::Response>,
869
-
AgentError,
870
-
>,
871
-
>
868
+
) -> impl Future<Output = Result<xrpc::Response<VecPutResponse<U>>, AgentError>>
872
869
where
873
870
U: VecUpdate,
874
871
<U as VecUpdate>::PutRequest: Send + Sync,
875
872
<U as VecUpdate>::GetRequest: Send + Sync,
876
-
<<U as VecUpdate>::GetRequest as XrpcRequest>::Response: Send + Sync,
877
-
<<U as VecUpdate>::PutRequest as XrpcRequest>::Response: Send + Sync,
873
+
VecGetResponse<U>: Send + Sync,
874
+
VecPutResponse<U>: Send + Sync,
878
875
{
879
876
async {
880
877
self.update_vec::<U>(|vec| {
···
944
941
}
945
942
946
943
impl<A: AgentSession + IdentityResolver> IdentityResolver for Agent<A> {
947
-
fn options(&self) -> &jacquard_identity::resolver::ResolverOptions {
944
+
fn options(&self) -> &ResolverOptions {
948
945
self.inner.options()
949
946
}
950
947
951
948
fn resolve_handle(
952
949
&self,
953
950
handle: &Handle<'_>,
954
-
) -> impl Future<Output = Result<Did<'static>, jacquard_identity::resolver::IdentityError>>
955
-
{
951
+
) -> impl Future<Output = Result<Did<'static>, IdentityError>> {
956
952
async { self.inner.resolve_handle(handle).await }
957
953
}
958
954
959
955
fn resolve_did_doc(
960
956
&self,
961
957
did: &Did<'_>,
962
-
) -> impl Future<
963
-
Output = Result<
964
-
jacquard_identity::resolver::DidDocResponse,
965
-
jacquard_identity::resolver::IdentityError,
966
-
>,
967
-
> {
958
+
) -> impl Future<Output = Result<DidDocResponse, IdentityError>> {
968
959
async { self.inner.resolve_did_doc(did).await }
969
960
}
970
961
}
+11
-13
crates/jacquard/src/client/credential_session.rs
+11
-13
crates/jacquard/src/client/credential_session.rs
···
9
9
http_client::HttpClient,
10
10
session::SessionStore,
11
11
types::{did::Did, string::Handle},
12
-
xrpc::{CallOptions, Response, XrpcClient, XrpcError, XrpcExt, XrpcRequest, XrpcResp},
12
+
xrpc::{
13
+
CallOptions, Response, XrpcClient, XrpcError, XrpcExt, XrpcRequest, XrpcResp, XrpcResponse,
14
+
},
13
15
};
14
16
use tokio::sync::RwLock;
15
17
use url::Url;
16
18
17
19
use crate::client::AtpSession;
18
-
use jacquard_identity::resolver::IdentityResolver;
20
+
use jacquard_identity::resolver::{
21
+
DidDocResponse, IdentityError, IdentityResolver, ResolverOptions,
22
+
};
19
23
use std::any::Any;
20
24
21
25
/// Storage key for app‑password sessions: `(account DID, session id)`.
···
426
430
}
427
431
}
428
432
429
-
async fn send<R>(&self, request: R) -> XrpcResult<Response<<R as XrpcRequest>::Response>>
433
+
async fn send<R>(&self, request: R) -> XrpcResult<XrpcResponse<R>>
430
434
where
431
435
R: XrpcRequest + Send + Sync,
432
436
<R as XrpcRequest>::Response: Send + Sync,
···
439
443
&self,
440
444
request: R,
441
445
mut opts: CallOptions<'_>,
442
-
) -> XrpcResult<Response<<R as XrpcRequest>::Response>>
446
+
) -> XrpcResult<XrpcResponse<R>>
443
447
where
444
448
R: XrpcRequest + Send + Sync,
445
449
<R as XrpcRequest>::Response: Send + Sync,
···
485
489
S: SessionStore<SessionKey, AtpSession> + Send + Sync + 'static,
486
490
T: HttpClient + IdentityResolver + Send + Sync + 'static,
487
491
{
488
-
fn options(&self) -> &jacquard_identity::resolver::ResolverOptions {
492
+
fn options(&self) -> &ResolverOptions {
489
493
self.client.options()
490
494
}
491
495
492
496
fn resolve_handle(
493
497
&self,
494
498
handle: &Handle<'_>,
495
-
) -> impl Future<Output = Result<Did<'static>, jacquard_identity::resolver::IdentityError>>
496
-
{
499
+
) -> impl Future<Output = Result<Did<'static>, IdentityError>> {
497
500
async { self.client.resolve_handle(handle).await }
498
501
}
499
502
500
503
fn resolve_did_doc(
501
504
&self,
502
505
did: &Did<'_>,
503
-
) -> impl Future<
504
-
Output = Result<
505
-
jacquard_identity::resolver::DidDocResponse,
506
-
jacquard_identity::resolver::IdentityError,
507
-
>,
508
-
> {
506
+
) -> impl Future<Output = Result<DidDocResponse, IdentityError>> {
509
507
async { self.client.resolve_did_doc(did).await }
510
508
}
511
509
}