diff --git a/README.md b/README.md index d9d1ffe..76b6245 100644 --- a/README.md +++ b/README.md @@ -309,12 +309,20 @@ cd rust/pubky/pubky-homeserver && cargo run -- --config=./src/config.toml cd example && yarn install && cd ios && pod install && cd ../ && yarn ios ``` -## Update Bindings +## Download Remote Bindings -After making changes to any of the Rust files, the bindings will need to be updated. To do this, run the following command: +This command will download the current bindings from the [SDK repo](https://github.com/pubky/pubky-core-mobile-sdk): ```sh -npm run update-bindings +npm run update-remote-bindings +``` + +## Setup Local Bindings + +This command will download the entire Rust project if it doesn't exist and set up the bindings locally for faster iteration and testing: + +```sh +npm run update-local-bindings ``` Finally, ensure that `PubkyModule.kt`, `Pubky.swift`, `Pubky.mm` & `src/index.tsx` are updated accordingly based on the changes made to the Rust files. diff --git a/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so b/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so index 079d6dd..8f508c9 100755 Binary files a/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so and b/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so b/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so index e605128..c52df25 100755 Binary files a/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so and b/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/x86/libpubkymobile.so b/android/src/main/jniLibs/x86/libpubkymobile.so index e00682b..f872f87 100755 Binary files a/android/src/main/jniLibs/x86/libpubkymobile.so and b/android/src/main/jniLibs/x86/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/x86_64/libpubkymobile.so b/android/src/main/jniLibs/x86_64/libpubkymobile.so index 889b893..6b7f080 100755 Binary files a/android/src/main/jniLibs/x86_64/libpubkymobile.so and b/android/src/main/jniLibs/x86_64/libpubkymobile.so differ diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/mobileFFI.h b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/mobileFFI.h deleted file mode 100644 index 82c6474..0000000 --- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/mobileFFI.h +++ /dev/null @@ -1,188 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! - -#pragma once - -#include -#include -#include - -// The following structs are used to implement the lowest level -// of the FFI, and thus useful to multiple uniffied crates. -// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H. -#ifdef UNIFFI_SHARED_H - // We also try to prevent mixing versions of shared uniffi header structs. - // If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4 - #ifndef UNIFFI_SHARED_HEADER_V4 - #error Combining helper code from multiple versions of uniffi is not supported - #endif // ndef UNIFFI_SHARED_HEADER_V4 -#else -#define UNIFFI_SHARED_H -#define UNIFFI_SHARED_HEADER_V4 -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ - -typedef struct RustBuffer -{ - int32_t capacity; - int32_t len; - uint8_t *_Nullable data; -} RustBuffer; - -typedef int32_t (*ForeignCallback)(uint64_t, int32_t, const uint8_t *_Nonnull, int32_t, RustBuffer *_Nonnull); - -// Task defined in Rust that Swift executes -typedef void (*UniFfiRustTaskCallback)(const void * _Nullable, int8_t); - -// Callback to execute Rust tasks using a Swift Task -// -// Args: -// executor: ForeignExecutor lowered into a size_t value -// delay: Delay in MS -// task: UniFfiRustTaskCallback to call -// task_data: data to pass the task callback -typedef int8_t (*UniFfiForeignExecutorCallback)(size_t, uint32_t, UniFfiRustTaskCallback _Nullable, const void * _Nullable); - -typedef struct ForeignBytes -{ - int32_t len; - const uint8_t *_Nullable data; -} ForeignBytes; - -// Error definitions -typedef struct RustCallStatus { - int8_t code; - RustBuffer errorBuf; -} RustCallStatus; - -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ -#endif // def UNIFFI_SHARED_H - -// Continuation callback for UniFFI Futures -typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t); - -// Scaffolding functions -void* _Nonnull uniffi_mobile_fn_func_auth(RustBuffer url, RustBuffer secret_key -); -RustBuffer ffi_mobile_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status -); -RustBuffer ffi_mobile_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status -); -RustBuffer ffi_mobile_rustbuffer_reserve(RustBuffer buf, int32_t additional, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_continuation_callback_set(UniFfiRustFutureContinuation _Nonnull callback -); -void ffi_mobile_rust_future_poll_u8(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u8(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u8(void* _Nonnull handle -); -uint8_t ffi_mobile_rust_future_complete_u8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i8(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i8(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i8(void* _Nonnull handle -); -int8_t ffi_mobile_rust_future_complete_i8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u16(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u16(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u16(void* _Nonnull handle -); -uint16_t ffi_mobile_rust_future_complete_u16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i16(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i16(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i16(void* _Nonnull handle -); -int16_t ffi_mobile_rust_future_complete_i16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u32(void* _Nonnull handle -); -uint32_t ffi_mobile_rust_future_complete_u32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i32(void* _Nonnull handle -); -int32_t ffi_mobile_rust_future_complete_i32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u64(void* _Nonnull handle -); -uint64_t ffi_mobile_rust_future_complete_u64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i64(void* _Nonnull handle -); -int64_t ffi_mobile_rust_future_complete_i64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_f32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_f32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_f32(void* _Nonnull handle -); -float ffi_mobile_rust_future_complete_f32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_f64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_f64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_f64(void* _Nonnull handle -); -double ffi_mobile_rust_future_complete_f64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_pointer(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_pointer(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_pointer(void* _Nonnull handle -); -void*_Nonnull ffi_mobile_rust_future_complete_pointer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_rust_buffer(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_rust_buffer(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_rust_buffer(void* _Nonnull handle -); -RustBuffer ffi_mobile_rust_future_complete_rust_buffer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_void(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_void(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_void(void* _Nonnull handle -); -void ffi_mobile_rust_future_complete_void(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -uint16_t uniffi_mobile_checksum_func_auth(void - -); -uint32_t ffi_mobile_uniffi_contract_version(void - -); - diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libmobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libmobile.a deleted file mode 100644 index 107f5e8..0000000 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libmobile.a and /dev/null differ diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a index d9a7acc..2804809 100644 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a and b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a differ diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/mobileFFI.h b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/mobileFFI.h deleted file mode 100644 index 82c6474..0000000 --- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/mobileFFI.h +++ /dev/null @@ -1,188 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! - -#pragma once - -#include -#include -#include - -// The following structs are used to implement the lowest level -// of the FFI, and thus useful to multiple uniffied crates. -// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H. -#ifdef UNIFFI_SHARED_H - // We also try to prevent mixing versions of shared uniffi header structs. - // If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4 - #ifndef UNIFFI_SHARED_HEADER_V4 - #error Combining helper code from multiple versions of uniffi is not supported - #endif // ndef UNIFFI_SHARED_HEADER_V4 -#else -#define UNIFFI_SHARED_H -#define UNIFFI_SHARED_HEADER_V4 -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ - -typedef struct RustBuffer -{ - int32_t capacity; - int32_t len; - uint8_t *_Nullable data; -} RustBuffer; - -typedef int32_t (*ForeignCallback)(uint64_t, int32_t, const uint8_t *_Nonnull, int32_t, RustBuffer *_Nonnull); - -// Task defined in Rust that Swift executes -typedef void (*UniFfiRustTaskCallback)(const void * _Nullable, int8_t); - -// Callback to execute Rust tasks using a Swift Task -// -// Args: -// executor: ForeignExecutor lowered into a size_t value -// delay: Delay in MS -// task: UniFfiRustTaskCallback to call -// task_data: data to pass the task callback -typedef int8_t (*UniFfiForeignExecutorCallback)(size_t, uint32_t, UniFfiRustTaskCallback _Nullable, const void * _Nullable); - -typedef struct ForeignBytes -{ - int32_t len; - const uint8_t *_Nullable data; -} ForeignBytes; - -// Error definitions -typedef struct RustCallStatus { - int8_t code; - RustBuffer errorBuf; -} RustCallStatus; - -// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️ -// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️ -#endif // def UNIFFI_SHARED_H - -// Continuation callback for UniFFI Futures -typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t); - -// Scaffolding functions -void* _Nonnull uniffi_mobile_fn_func_auth(RustBuffer url, RustBuffer secret_key -); -RustBuffer ffi_mobile_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status -); -RustBuffer ffi_mobile_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status -); -RustBuffer ffi_mobile_rustbuffer_reserve(RustBuffer buf, int32_t additional, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_continuation_callback_set(UniFfiRustFutureContinuation _Nonnull callback -); -void ffi_mobile_rust_future_poll_u8(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u8(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u8(void* _Nonnull handle -); -uint8_t ffi_mobile_rust_future_complete_u8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i8(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i8(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i8(void* _Nonnull handle -); -int8_t ffi_mobile_rust_future_complete_i8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u16(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u16(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u16(void* _Nonnull handle -); -uint16_t ffi_mobile_rust_future_complete_u16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i16(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i16(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i16(void* _Nonnull handle -); -int16_t ffi_mobile_rust_future_complete_i16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u32(void* _Nonnull handle -); -uint32_t ffi_mobile_rust_future_complete_u32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i32(void* _Nonnull handle -); -int32_t ffi_mobile_rust_future_complete_i32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_u64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_u64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_u64(void* _Nonnull handle -); -uint64_t ffi_mobile_rust_future_complete_u64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_i64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_i64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_i64(void* _Nonnull handle -); -int64_t ffi_mobile_rust_future_complete_i64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_f32(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_f32(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_f32(void* _Nonnull handle -); -float ffi_mobile_rust_future_complete_f32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_f64(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_f64(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_f64(void* _Nonnull handle -); -double ffi_mobile_rust_future_complete_f64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_pointer(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_pointer(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_pointer(void* _Nonnull handle -); -void*_Nonnull ffi_mobile_rust_future_complete_pointer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_rust_buffer(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_rust_buffer(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_rust_buffer(void* _Nonnull handle -); -RustBuffer ffi_mobile_rust_future_complete_rust_buffer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -void ffi_mobile_rust_future_poll_void(void* _Nonnull handle, void* _Nonnull uniffi_callback -); -void ffi_mobile_rust_future_cancel_void(void* _Nonnull handle -); -void ffi_mobile_rust_future_free_void(void* _Nonnull handle -); -void ffi_mobile_rust_future_complete_void(void* _Nonnull handle, RustCallStatus *_Nonnull out_status -); -uint16_t uniffi_mobile_checksum_func_auth(void - -); -uint32_t ffi_mobile_uniffi_contract_version(void - -); - diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libmobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libmobile.a deleted file mode 100644 index 90a9168..0000000 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libmobile.a and /dev/null differ diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a index d6dea34..437fa01 100644 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a and b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a differ diff --git a/package.json b/package.json index de11963..25d300b 100644 --- a/package.json +++ b/package.json @@ -46,11 +46,15 @@ "example:ios": "cd example && cd ios && rm -rf Pods && cd ../ && npm i && bundle install && npm run build:ios && npm run ios", "example:android": "cd example && npm i && npm run build:android && npm run android", "reinstall": "yarn install && npm run clean && npm run prepare", - "cargo-build": "cd rust && cargo build && cd pubky && cargo build && cd pubky && cargo build && cd ../ && cd pubky-common && cargo build && cd ../ && cd pubky-homeserver && cargo build && cd ../../../", - "update-bindings:ios": "npm run cargo-build && node setup-ios-bindings.js && npm run reinstall", - "update-bindings:android": "npm run cargo-build && node setup-android-bindings.js && npm run reinstall", - "update-bindings": "npm run reinstall && npm run cargo-build && npm run update-bindings:ios && npm run update-bindings:android", - "rebuild": "rm -rf node_modules && cd example && rm -rf node_modules && cd ios && rm -rf Pods Podfile.lock build && cd ../../ && npm run cargo-build && yarn install && npm run update-bindings && cd example && yarn install && bundle install && cd ios && pod install && cd ../ && yarn build:ios && yarn ios" + "cargo-build": "yarn install && node setup-rust.js && cd rust && cargo build && cd pubky && cargo build && cd pubky && cargo build && cd ../ && cd pubky-common && cargo build && cd ../ && cd pubky-homeserver && cargo build && cd ../../../", + "update-local-bindings:ios": "npm run cargo-build && cd rust && ./build.sh ios && cd ../ && node setup-local-ios-bindings.js && npm run reinstall", + "update-local-bindings:android": "npm run cargo-build && cd rust && ./build.sh android && cd ../ && node setup-local-android-bindings.js && npm run reinstall", + "update-local-bindings": "npm run reinstall && npm run cargo-build && npm run update-local-bindings:ios && npm run update-local-bindings:android", + "rebuild-local": "rm -rf node_modules && cd example && rm -rf node_modules && cd ios && rm -rf Pods Podfile.lock build && cd ../../ && npm run cargo-build && yarn install && npm run update-local-bindings && cd example && yarn install && bundle install && cd ios && pod install && cd ../ && yarn build:ios && yarn ios", + "update-remote-bindings:ios": "node setup-remote-ios-bindings.js && npm run reinstall", + "update-remote-bindings:android": "node setup-remote-android-bindings.js && npm run reinstall", + "update-remote-bindings": "npm run reinstall && npm run update-remote-bindings:ios && npm run update-remote-bindings:android", + "rebuild-remote": "rm -rf node_modules && cd example && rm -rf node_modules && cd ios && rm -rf Pods Podfile.lock build && cd ../../ && yarn install && npm run update-remote-bindings && cd example && yarn install && bundle install && cd ios && pod install && cd ../ && yarn build:ios && yarn ios" }, "keywords": [ "pubky", @@ -69,7 +73,7 @@ }, "homepage": "https://github.com/pubky/react-native-pubky#readme", "publishConfig": { - "access": "restricted", + "access": "public", "registry": "https://registry.npmjs.org/" }, "dependencies": { @@ -93,6 +97,7 @@ "react-native": "0.75.3", "react-native-builder-bob": "^0.30.2", "release-it": "^15.0.0", + "simple-git": "^3.27.0", "turbo": "^1.10.7", "typescript": "^5.2.2" }, diff --git a/rust/Cargo.lock b/rust/Cargo.lock deleted file mode 100644 index a72ef83..0000000 --- a/rust/Cargo.lock +++ /dev/null @@ -1,3140 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "askama" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" -dependencies = [ - "askama_derive", - "askama_escape", -] - -[[package]] -name = "askama_derive" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" -dependencies = [ - "askama_parser", - "basic-toml", - "mime", - "mime_guess", - "proc-macro2", - "quote", - "serde", - "syn", -] - -[[package]] -name = "askama_escape" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" - -[[package]] -name = "askama_parser" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" -dependencies = [ - "nom", -] - -[[package]] -name = "async-trait" -version = "0.1.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "axum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core", - "axum-macros", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-extra" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" -dependencies = [ - "axum", - "axum-core", - "bytes", - "futures-util", - "headers", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "serde", - "tokio", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "basic-toml" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" -dependencies = [ - "serde", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -dependencies = [ - "serde", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "blake3" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cc" -version = "1.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clap" -version = "4.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" -dependencies = [ - "cookie", - "idna 0.5.0", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "critical-section" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "crypto_secretbox" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" -dependencies = [ - "aead", - "cipher", - "generic-array", - "poly1305", - "salsa20", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "document-features" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" -dependencies = [ - "litrs", -] - -[[package]] -name = "doxygen-rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" -dependencies = [ - "phf", -] - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "serde", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core", - "serde", - "sha2", - "subtle", - "zeroize", -] - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs-err" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" -dependencies = [ - "autocfg", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "goblin" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" -dependencies = [ - "log", - "plain", - "scroll", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "headers" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "heed" -version = "0.20.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4f449bab7320c56003d37732a917e18798e2f1709d80263face2b4f9436ddb" -dependencies = [ - "bitflags", - "byteorder", - "heed-traits", - "heed-types", - "libc", - "lmdb-master-sys", - "once_cell", - "page_size", - "serde", - "synchronoise", - "url", -] - -[[package]] -name = "heed-traits" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" - -[[package]] -name = "heed-types" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d3f528b053a6d700b2734eabcd0fd49cb8230647aa72958467527b0b7917114" -dependencies = [ - "bincode", - "byteorder", - "heed-traits", - "serde", - "serde_json", -] - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnet" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - -[[package]] -name = "lmdb-master-sys" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "472c3760e2a8d0f61f322fb36788021bb36d573c502b50fa3e2bcaac3ec326c9" -dependencies = [ - "cc", - "doxygen-rs", - "libc", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lru" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" - -[[package]] -name = "mainline" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b751ffb57303217bcae8f490eee6044a5b40eadf6ca05ff476cad37e7b7970d" -dependencies = [ - "bytes", - "crc", - "ed25519-dalek", - "flume", - "lru", - "rand", - "serde", - "serde_bencode", - "serde_bytes", - "sha1_smol", - "thiserror", - "tracing", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "object" -version = "0.36.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "oneshot-uniffi" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkarr" -version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=v3#5b2f8e53735f63521b0d587167609a2cb9b8f2ab" -dependencies = [ - "base32", - "bytes", - "document-features", - "dyn-clone", - "ed25519-dalek", - "flume", - "futures", - "js-sys", - "lru", - "mainline", - "rand", - "self_cell", - "serde", - "simple-dns", - "thiserror", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "postcard" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" -dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "heapless", - "serde", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "pubky" -version = "0.1.0" -dependencies = [ - "base64 0.22.1", - "bytes", - "js-sys", - "pkarr", - "pubky-common", - "reqwest", - "thiserror", - "tokio", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", -] - -[[package]] -name = "pubky-common" -version = "0.1.0" -dependencies = [ - "argon2", - "base32", - "blake3", - "crypto_secretbox", - "ed25519-dalek", - "js-sys", - "once_cell", - "pkarr", - "postcard", - "rand", - "serde", - "thiserror", -] - -[[package]] -name = "pubky_homeserver" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "axum-extra", - "base32", - "bytes", - "clap", - "dirs-next", - "flume", - "futures-util", - "heed", - "hex", - "pkarr", - "postcard", - "pubky-common", - "serde", - "tokio", - "toml 0.8.19", - "tower-cookies", - "tower-http", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "publicsuffix" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" -dependencies = [ - "idna 0.3.0", - "psl-types", -] - -[[package]] -name = "quinn" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" -dependencies = [ - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "react_native_pubky" -version = "0.1.0" -dependencies = [ - "base64 0.22.1", - "hex", - "once_cell", - "pkarr", - "pubky", - "pubky-common", - "pubky_homeserver", - "serde", - "serde_json", - "sha2", - "tokio", - "uniffi", - "url", -] - -[[package]] -name = "redox_syscall" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.12.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" -dependencies = [ - "base64 0.22.1", - "bytes", - "cookie", - "cookie_store", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustls" -version = "0.23.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scroll" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "self_cell" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -dependencies = [ - "serde", -] - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bencode" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70dfc7b7438b99896e7f8992363ab8e2c4ba26aa5ec675d32d1c3c2c33d413e" -dependencies = [ - "serde", - "serde_bytes", -] - -[[package]] -name = "serde_bytes" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "rand_core", -] - -[[package]] -name = "simple-dns" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01607fe2e61894468c6dc0b26103abb073fb08b79a3d9e4b6d76a1a341549958" -dependencies = [ - "bitflags", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synchronoise" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" -dependencies = [ - "crossbeam-queue", -] - -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-cookies" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d" -dependencies = [ - "async-trait", - "axum-core", - "cookie", - "futures-util", - "http", - "parking_lot", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" -dependencies = [ - "bitflags", - "bytes", - "http", - "http-body", - "http-body-util", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "uniffi" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21345172d31092fd48c47fd56c53d4ae9e41c4b1f559fb8c38c1ab1685fd919f" -dependencies = [ - "anyhow", - "camino", - "clap", - "uniffi_bindgen", - "uniffi_core", - "uniffi_macros", -] - -[[package]] -name = "uniffi_bindgen" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd992f2929a053829d5875af1eff2ee3d7a7001cb3b9a46cc7895f2caede6940" -dependencies = [ - "anyhow", - "askama", - "camino", - "cargo_metadata", - "clap", - "fs-err", - "glob", - "goblin", - "heck 0.4.1", - "once_cell", - "paste", - "serde", - "toml 0.5.11", - "uniffi_meta", - "uniffi_testing", - "uniffi_udl", -] - -[[package]] -name = "uniffi_build" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001964dd3682d600084b3aaf75acf9c3426699bc27b65e96bb32d175a31c74e9" -dependencies = [ - "anyhow", - "camino", - "uniffi_bindgen", -] - -[[package]] -name = "uniffi_checksum_derive" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55137c122f712d9330fd985d66fa61bdc381752e89c35708c13ce63049a3002c" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "uniffi_core" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6121a127a3af1665cd90d12dd2b3683c2643c5103281d0fed5838324ca1fad5b" -dependencies = [ - "anyhow", - "bytes", - "camino", - "log", - "once_cell", - "oneshot-uniffi", - "paste", - "static_assertions", -] - -[[package]] -name = "uniffi_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11cf7a58f101fcedafa5b77ea037999b88748607f0ef3a33eaa0efc5392e92e4" -dependencies = [ - "bincode", - "camino", - "fs-err", - "once_cell", - "proc-macro2", - "quote", - "serde", - "syn", - "toml 0.5.11", - "uniffi_build", - "uniffi_meta", -] - -[[package]] -name = "uniffi_meta" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dc8573a7b1ac4b71643d6da34888273ebfc03440c525121f1b3634ad3417a2" -dependencies = [ - "anyhow", - "bytes", - "siphasher", - "uniffi_checksum_derive", -] - -[[package]] -name = "uniffi_testing" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "118448debffcb676ddbe8c5305fb933ab7e0123753e659a71dc4a693f8d9f23c" -dependencies = [ - "anyhow", - "camino", - "cargo_metadata", - "fs-err", - "once_cell", -] - -[[package]] -name = "uniffi_udl" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "889edb7109c6078abe0e53e9b4070cf74a6b3468d141bdf5ef1bd4d1dc24a1c3" -dependencies = [ - "anyhow", - "uniffi_meta", - "uniffi_testing", - "weedle2", -] - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "web-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "weedle2" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e79c5206e1f43a2306fd64bdb95025ee4228960f2e6c5a8b173f3caaf807741" -dependencies = [ - "nom", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" -dependencies = [ - "memchr", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/rust/Cargo.toml b/rust/Cargo.toml deleted file mode 100644 index 1e1aa4c..0000000 --- a/rust/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "react_native_pubky" -version = "0.1.0" -edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate_type = ["cdylib", "staticlib"] -name = "pubkymobile" - -[[bin]] -name = "testing" -path = "testing/main.rs" - -[net] -git-fetch-with-cli = true - -[dependencies] -uniffi = { version = "0.25.3", features = [ "cli" ] } -serde_json = "1.0.114" -hex = "0.4.3" -sha2 = "0.10.8" -serde = { version = "^1.0.209", features = ["derive"] } -tokio = "1.40.0" -url = "2.5.2" -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", features = ["async", "rand"] } -pubky = { version = "0.1.0", path = "pubky/pubky" } -pubky-common = { version = "0.1.0", path = "pubky/pubky-common" } -pubky_homeserver = { version = "0.1.0", path = "pubky/pubky-homeserver" } -base64 = "0.22.1" -once_cell = "1.19.0" diff --git a/rust/bindings/module.modulemap b/rust/bindings/module.modulemap deleted file mode 100644 index 09b533a..0000000 --- a/rust/bindings/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -// This file was autogenerated by some hot garbage in the `uniffi` crate. -// Trust me, you don't want to mess with it! -module pubkymobileFFI { - header "pubkymobileFFI.h" - export * -} \ No newline at end of file diff --git a/rust/pubky/Cargo.lock b/rust/pubky/Cargo.lock deleted file mode 100644 index a712105..0000000 --- a/rust/pubky/Cargo.lock +++ /dev/null @@ -1,2811 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-trait" -version = "0.1.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "authenticator" -version = "0.1.0" -dependencies = [ - "anyhow", - "base64 0.22.1", - "clap", - "pubky", - "pubky-common", - "rpassword", - "tokio", - "url", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "axum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core", - "axum-macros", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-extra" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" -dependencies = [ - "axum", - "axum-core", - "bytes", - "futures-util", - "headers", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "serde", - "tokio", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -dependencies = [ - "serde", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "blake3" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cc" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e2d530f35b40a84124146478cd16f34225306a8441998836466a2e2961c950" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clap" -version = "4.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" -dependencies = [ - "cookie", - "idna 0.5.0", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "critical-section" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "crypto_secretbox" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" -dependencies = [ - "aead", - "cipher", - "generic-array", - "poly1305", - "salsa20", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "document-features" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" -dependencies = [ - "litrs", -] - -[[package]] -name = "doxygen-rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" -dependencies = [ - "phf", -] - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "serde", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core", - "serde", - "sha2", - "subtle", - "zeroize", -] - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "headers" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "heed" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc30da4a93ff8cb98e535d595d6de42731d4719d707bc1c86f579158751a24e" -dependencies = [ - "bitflags", - "byteorder", - "heed-traits", - "heed-types", - "libc", - "lmdb-master-sys", - "once_cell", - "page_size", - "serde", - "synchronoise", - "url", -] - -[[package]] -name = "heed-traits" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" - -[[package]] -name = "heed-types" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d3f528b053a6d700b2734eabcd0fd49cb8230647aa72958467527b0b7917114" -dependencies = [ - "bincode", - "byteorder", - "heed-traits", - "serde", - "serde_json", -] - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - -[[package]] -name = "lmdb-master-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57640c190703d5ccf4a86aff4aeb749b2d287a8cb1723c76b51f39d77ab53b24" -dependencies = [ - "cc", - "doxygen-rs", - "libc", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" - -[[package]] -name = "mainline" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b751ffb57303217bcae8f490eee6044a5b40eadf6ca05ff476cad37e7b7970d" -dependencies = [ - "bytes", - "crc", - "ed25519-dalek", - "flume", - "lru", - "rand", - "serde", - "serde_bencode", - "serde_bytes", - "sha1_smol", - "thiserror", - "tracing", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "object" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkarr" -version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=v3#17975121c809d97dcad907fbb2ffc782e994d270" -dependencies = [ - "base32", - "bytes", - "document-features", - "dyn-clone", - "ed25519-dalek", - "flume", - "futures", - "js-sys", - "lru", - "mainline", - "rand", - "self_cell", - "serde", - "simple-dns", - "thiserror", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "postcard" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" -dependencies = [ - "cobs", - "embedded-io", - "heapless", - "serde", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "pubky" -version = "0.1.0" -dependencies = [ - "base64 0.22.1", - "bytes", - "js-sys", - "pkarr", - "pubky-common", - "pubky_homeserver", - "reqwest", - "thiserror", - "tokio", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", -] - -[[package]] -name = "pubky-common" -version = "0.1.0" -dependencies = [ - "argon2", - "base32", - "blake3", - "crypto_secretbox", - "ed25519-dalek", - "js-sys", - "once_cell", - "pkarr", - "postcard", - "rand", - "serde", - "thiserror", -] - -[[package]] -name = "pubky_homeserver" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "axum-extra", - "base32", - "bytes", - "clap", - "dirs-next", - "flume", - "futures-util", - "heed", - "hex", - "pkarr", - "postcard", - "pubky-common", - "serde", - "tokio", - "toml", - "tower-cookies", - "tower-http", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "publicsuffix" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" -dependencies = [ - "idna 0.3.0", - "psl-types", -] - -[[package]] -name = "quinn" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" -dependencies = [ - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "cookie", - "cookie_store", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rpassword" -version = "7.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" -dependencies = [ - "libc", - "rtoolbox", - "windows-sys 0.48.0", -] - -[[package]] -name = "rtoolbox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustls" -version = "0.23.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" - -[[package]] -name = "rustls-webpki" -version = "0.102.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "self_cell" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.209" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bencode" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70dfc7b7438b99896e7f8992363ab8e2c4ba26aa5ec675d32d1c3c2c33d413e" -dependencies = [ - "serde", - "serde_bytes", -] - -[[package]] -name = "serde_bytes" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.209" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "rand_core", -] - -[[package]] -name = "simple-dns" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01607fe2e61894468c6dc0b26103abb073fb08b79a3d9e4b6d76a1a341549958" -dependencies = [ - "bitflags", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "synchronoise" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" -dependencies = [ - "crossbeam-queue", -] - -[[package]] -name = "thiserror" -version = "1.0.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-cookies" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d" -dependencies = [ - "async-trait", - "axum-core", - "cookie", - "futures-util", - "http", - "parking_lot", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" -dependencies = [ - "bitflags", - "bytes", - "http", - "http-body", - "http-body-util", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "web-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/rust/pubky/Cargo.toml b/rust/pubky/Cargo.toml deleted file mode 100644 index 8514809..0000000 --- a/rust/pubky/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[workspace] -members = [ - "pubky", - "pubky-*", - - "examples/authz/authenticator" -] - -# See: https://github.com/rust-lang/rust/issues/90148#issuecomment-949194352 -resolver = "2" - -[workspace.dependencies] -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr", features = ["async"] } -serde = { version = "^1.0.209", features = ["derive"] } - -[profile.release] -lto = true -opt-level = 'z' diff --git a/rust/pubky/LICENSE b/rust/pubky/LICENSE deleted file mode 100644 index a0e67c5..0000000 --- a/rust/pubky/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/rust/pubky/README.md b/rust/pubky/README.md deleted file mode 100644 index 23197ae..0000000 --- a/rust/pubky/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Pubky - -> The Web, long centralized, must decentralize; Long decentralized, must centralize. - -> [!WARNING] -> Pubky is still under heavy development and should be considered an alpha software. -> -> Features might be added, removed, or changed. Data might be lost. diff --git a/rust/pubky/examples/authz/3rd-party-app/.gitignore b/rust/pubky/examples/authz/3rd-party-app/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/rust/pubky/examples/authz/3rd-party-app/index.html b/rust/pubky/examples/authz/3rd-party-app/index.html deleted file mode 100644 index d2c0901..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - Pubky Auth Demo - - - - - - - - -
-

Third Party app!

-

this is a demo for using Pubky Auth in an unhosted (no backend) app.

-
- - -
-
- - diff --git a/rust/pubky/examples/authz/3rd-party-app/package-lock.json b/rust/pubky/examples/authz/3rd-party-app/package-lock.json deleted file mode 100644 index fe0ff66..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/package-lock.json +++ /dev/null @@ -1,1136 +0,0 @@ -{ - "name": "pubky-auth-3rd-party", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "pubky-auth-3rd-party", - "version": "0.0.0", - "dependencies": { - "@synonymdev/pubky": "^0.1.16", - "lit": "^3.2.0", - "qrcode": "^1.5.4" - }, - "devDependencies": { - "vite": "^5.4.2" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", - "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" - }, - "node_modules/@lit/reactive-element": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", - "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", - "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", - "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", - "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", - "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", - "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", - "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", - "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", - "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", - "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", - "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", - "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", - "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", - "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", - "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", - "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", - "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@synonymdev/pubky": { - "version": "0.1.16", - "resolved": "https://registry.npmjs.org/@synonymdev/pubky/-/pubky-0.1.16.tgz", - "integrity": "sha512-jtFahEUUDfrTE7vpZx6m/uB4wMEBoqpEtuUoWCf30HH8cmm0Hfrv8v0xmwaSwPfSdcZlIG8beE5XjbX+eLmLUA==" - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/lit": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.0.tgz", - "integrity": "sha512-s6tI33Lf6VpDu7u4YqsSX78D28bYQulM+VAzsGch4fx2H0eLZnJsUBsPWmGYSGoKDNbjtRv02rio1o+UdPVwvw==", - "dependencies": { - "@lit/reactive-element": "^2.0.4", - "lit-element": "^4.1.0", - "lit-html": "^3.2.0" - } - }, - "node_modules/lit-element": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.0.tgz", - "integrity": "sha512-gSejRUQJuMQjV2Z59KAS/D4iElUhwKpIyJvZ9w+DIagIQjfJnhR20h2Q5ddpzXGS+fF0tMZ/xEYGMnKmaI/iww==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", - "@lit/reactive-element": "^2.0.4", - "lit-html": "^3.2.0" - } - }, - "node_modules/lit-html": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.0.tgz", - "integrity": "sha512-pwT/HwoxqI9FggTrYVarkBKFN9MlTUpLrDHubTmW4SrkL3kkqW5gxwbxMMUnbbRHBC0WTZnYHcjDSCM559VyfA==", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/postcss": { - "version": "8.4.42", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.42.tgz", - "integrity": "sha512-hywKUQB9Ra4dR1mGhldy5Aj1X3MWDSIA1cEi+Uy0CjheLvP6Ual5RlwMCh8i/X121yEDLDIKBsrCQ8ba3FDMfQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/qrcode": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "dependencies": { - "dijkstrajs": "^1.0.1", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/rollup": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", - "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.2", - "@rollup/rollup-android-arm64": "4.21.2", - "@rollup/rollup-darwin-arm64": "4.21.2", - "@rollup/rollup-darwin-x64": "4.21.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", - "@rollup/rollup-linux-arm-musleabihf": "4.21.2", - "@rollup/rollup-linux-arm64-gnu": "4.21.2", - "@rollup/rollup-linux-arm64-musl": "4.21.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", - "@rollup/rollup-linux-riscv64-gnu": "4.21.2", - "@rollup/rollup-linux-s390x-gnu": "4.21.2", - "@rollup/rollup-linux-x64-gnu": "4.21.2", - "@rollup/rollup-linux-x64-musl": "4.21.2", - "@rollup/rollup-win32-arm64-msvc": "4.21.2", - "@rollup/rollup-win32-ia32-msvc": "4.21.2", - "@rollup/rollup-win32-x64-msvc": "4.21.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/vite": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", - "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.41", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - } - } -} diff --git a/rust/pubky/examples/authz/3rd-party-app/package.json b/rust/pubky/examples/authz/3rd-party-app/package.json deleted file mode 100644 index 0a99f66..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "pubky-auth-3rd-party", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "start": "npm run dev", - "dev": "vite --host --open", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "@synonymdev/pubky": "^0.1.16", - "lit": "^3.2.0", - "qrcode": "^1.5.4" - }, - "devDependencies": { - "vite": "^5.4.2" - } -} diff --git a/rust/pubky/examples/authz/3rd-party-app/public/pubky.svg b/rust/pubky/examples/authz/3rd-party-app/public/pubky.svg deleted file mode 100644 index e24e21d..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/public/pubky.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - diff --git a/rust/pubky/examples/authz/3rd-party-app/src/index.css b/rust/pubky/examples/authz/3rd-party-app/src/index.css deleted file mode 100644 index 809fde4..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/src/index.css +++ /dev/null @@ -1,48 +0,0 @@ -:root { - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', - Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - color: white; - - background: radial-gradient( - circle, - transparent 20%, - #151718 20%, - #151718 80%, - transparent 80%, - transparent - ), - radial-gradient( - circle, - transparent 20%, - #151718 20%, - #151718 80%, - transparent 80%, - transparent - ) - 25px 25px, - linear-gradient(#202020 1px, transparent 2px) 0 -1px, - linear-gradient(90deg, #202020 1px, #151718 2px) -1px 0; - background-size: 50px 50px, 50px 50px, 25px 25px, 25px 25px; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 20rem; - min-height: 100vh; - font-family: var(--font-family); -} - -h1 { - font-weight: bold; - font-size: 3.2rem; - line-height: 1.1; -} - -main { - max-width: 80rem; - margin: 0 auto; - padding: 2rem; - text-align: center; -} diff --git a/rust/pubky/examples/authz/3rd-party-app/src/pubky-auth-widget.js b/rust/pubky/examples/authz/3rd-party-app/src/pubky-auth-widget.js deleted file mode 100644 index 628f316..0000000 --- a/rust/pubky/examples/authz/3rd-party-app/src/pubky-auth-widget.js +++ /dev/null @@ -1,391 +0,0 @@ -import { LitElement, css, html } from 'lit' -import { createRef, ref } from 'lit/directives/ref.js'; -import QRCode from 'qrcode' - -const DEFAULT_HTTP_RELAY = "https://demo.httprelay.io/link" - -/** - */ -export class PubkyAuthWidget extends LitElement { - - static get properties() { - return { - // === Config === - - /** - * Relay endpoint for the widget to receive Pubky AuthTokens - * - * Internally, a random channel ID will be generated and a - * GET request made for `${realy url}/${channelID}` - * - * If no relay is passed, the widget will use a default relay: - * https://demo.httprelay.io/link - */ - relay: { type: String }, - /** - * Capabilities requested or this application encoded as a string. - */ - caps: { type: String }, - - // === State === - - /** - * Widget's state (open or closed) - */ - open: { type: Boolean }, - /** - * Show "copied to clipboard" note - */ - showCopied: { type: Boolean }, - - // === Internal === - testnet: { type: Boolean }, - pubky: { type: Object } - } - } - - canvasRef = createRef(); - - constructor() { - if (!window.pubky) { - throw new Error("window.pubky is unavailable, make sure to import `@synonymdev/pubky` before this web component.") - } - - super() - - this.testnet = false; - this.open = false; - - /** @type {import("@synonymdev/pubky").PubkyClient} */ - this.pubkyClient = new window.pubky.PubkyClient(); - - this.caps = this.caps || "" - } - - connectedCallback() { - super.connectedCallback() - - this._generateURL() - } - - switchTestnet() { - this.testnet = !this.testnet; - - console.debug("Switching testnet"); - - if (this.testnet) { - this.pubkyClient = window.pubky.PubkyClient.testnet() - } else { - this.pubkyClient = new window.pubky.PubkyClient(); - } - - console.debug("Pkarr Relays: " + this.pubkyClient.getPkarrRelays()) - - this._generateURL() - } - - setCapabilities(caps) { - this.caps = caps || "" - - this._generateURL(this.caps); - console.debug("Updated capabilities"); - } - - - _generateURL() { - let [url, promise] = this.pubkyClient.authRequest(this.relay || DEFAULT_HTTP_RELAY, this.caps); - - promise.then(pubky => { - this.pubky = pubky.z32(); - }).catch(e => { - console.error(e) - }) - - this.authUrl = url - - this._updateQr(); - } - - _updateQr() { - if (this.canvas) { - this._setQr(this.canvas); - } - } - - _setQr(canvas) { - this.canvas = canvas - QRCode.toCanvas(canvas, this.authUrl, { - margin: 2, - scale: 8, - - color: { - light: '#fff', - dark: '#000', - }, - }); - } - - _switchOpen() { - this.open = !this.open - setTimeout(() => { this.pubky = null }, 80) - } - - async _copyToClipboard() { - try { - await navigator.clipboard.writeText(this.authUrl); - this.showCopied = true; - setTimeout(() => { this.showCopied = false }, 1000) - } catch (error) { - console.error('Failed to copy text: ', error); - } - } - - - - render() { - return html` -
- -
-
- ${this.pubky - ? this.caps.length > 0 - ? html` -

Successfully authorized:

-

${this.pubky}

-

With capabilities

- ${this.caps.split(",").map(cap => html` -

${cap}

- `) - } - ` - : html` -

Successfully authenticated to:

-

${this.pubky}

- ` - : html` -

Scan or copy Pubky auth URL

-
- -
- - ` - } -
-
- ` - } - - _renderWidgetContentBase() { - } - - - static get styles() { - return css` - * { - box-sizing: border-box; - } - - :host { - --full-width: 22rem; - --full-height: 31rem; - --header-height: 3rem; - --closed-width: 3rem; - } - - a { - text-decoration: none; - } - - button { - padding: 0; - background: none; - border: none; - color: inherit; - cursor: pointer; - } - - p { - margin: 0; - } - - /** End reset */ - - #widget { - color: white; - - position: fixed; - top: 1rem; - right: 1rem; - - background-color:red; - - z-index: 99999; - overflow: hidden; - background: rgba(43, 43, 43, .7372549019607844); - border: 1px solid #3c3c3c; - box-shadow: 0 10px 34px -10px rgba(236, 243, 222, .05); - border-radius: 8px; - -webkit-backdrop-filter: blur(8px); - backdrop-filter: blur(8px); - - width: var(--closed-width); - height: var(--header-height); - - will-change: height,width; - transition-property: height, width; - transition-duration: 80ms; - transition-timing-function: ease-in; - } - - #widget.open{ - width: var(--full-width); - height: var(--full-height); - } - - .header { - width: 100%; - height: var(--header-height); - display: flex; - justify-content: center; - align-items:center; - } - - .header-content { - display: flex; - justify-content: center; - align-items: baseline; - column-gap: .5rem; - } - - #widget - .header .text { - display: none; - font-weight: bold; - font-size: 1.5rem; - } - #widget.open - .header .text { - display: block - } - - #widget.open - .header { - width: var(--full-width); - justify-content: center; - } - - #pubky-icon { - height: 1.5rem; - width: 100%; - } - - #widget.open - #pubky-icon { - width: auto; - } - - #widget-content{ - width: var(--full-width); - padding: 0 1rem - } - - #widget p { - font-size: .87rem; - line-height: 1rem; - text-align: center; - color: #fff; - opacity: .5; - - /* Fix flash wrap in open animation */ - text-wrap: nowrap; - } - - #qr { - width: 18em !important; - height: 18em !important; - } - - .card { - position: relative; - background: #3b3b3b; - border-radius: 5px; - padding: 1rem; - margin-top: 1rem; - display: flex; - justify-content: center; - align-items: center; - } - - .card.url { - padding: .625rem; - justify-content: space-between; - max-width:100%; - } - - .url p { - display: flex; - align-items: center; - - line-height: 1!important; - width: 93%; - overflow: hidden; - text-overflow: ellipsis; - text-wrap: nowrap; - } - - .line { - height: 1px; - background-color: #3b3b3b; - flex: 1 1; - margin-bottom: 1rem; - } - - .copied { - will-change: opacity; - transition-property: opacity; - transition-duration: 80ms; - transition-timing-function: ease-in; - - opacity: 0; - - position: absolute; - right: 0; - top: -1.6rem; - font-size: 0.9em; - background: rgb(43 43 43 / 98%); - padding: .5rem; - border-radius: .3rem; - color: #ddd; - } - - .copied.show { - opacity:1 - } - ` - } -} - -window.customElements.define('pubky-auth-widget', PubkyAuthWidget) diff --git a/rust/pubky/examples/authz/README.md b/rust/pubky/examples/authz/README.md deleted file mode 100644 index 905bda6..0000000 --- a/rust/pubky/examples/authz/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Pubky Auth Example - -This example shows 3rd party authorization in Pubky. - -It consists of 2 parts: - -1. [3rd party app](./3rd-party-app): A web component showing the how to implement a Pubky Auth widget. -2. [Authenticator CLI](./authenticator): A CLI showing the authenticator (key chain) asking user for consent and generating the AuthToken. - -## Usage - -First you need to be running a local testnet Homeserver, in the root of this repo run - -```bash -cargo run --bin pubky_homeserver -- --testnet -``` - -Run the frontend of the 3rd party app - -```bash -cd ./3rd-party-app -npm start -``` - -Copy the Pubky Auth URL from the frontend. - -Finally run the CLI to paste the Pubky Auth in. - -You should see the frontend reacting by showing the success of authorization and session details. diff --git a/rust/pubky/examples/authz/authenticator/Cargo.toml b/rust/pubky/examples/authz/authenticator/Cargo.toml deleted file mode 100644 index 932701b..0000000 --- a/rust/pubky/examples/authz/authenticator/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "authenticator" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0.86" -base64 = "0.22.1" -clap = { version = "4.5.16", features = ["derive"] } -pubky = { version = "0.1.0", path = "../../../pubky" } -pubky-common = { version = "0.1.0", path = "../../../pubky-common" } -rpassword = "7.3.1" -tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } -url = "2.5.2" diff --git a/rust/pubky/examples/authz/authenticator/src/main.rs b/rust/pubky/examples/authz/authenticator/src/main.rs deleted file mode 100644 index 410b8f5..0000000 --- a/rust/pubky/examples/authz/authenticator/src/main.rs +++ /dev/null @@ -1,80 +0,0 @@ -use anyhow::Result; -use clap::Parser; -use pubky::PubkyClient; -use std::path::PathBuf; -use url::Url; - -use pubky_common::{capabilities::Capability, crypto::PublicKey}; - -/// local testnet HOMESERVER -const HOMESERVER: &str = "8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"; - -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -struct Cli { - /// Path to a recovery_file of the Pubky you want to sign in with - recovery_file: PathBuf, - - /// Pubky Auth url - url: Url, -} - -#[tokio::main] -async fn main() -> Result<()> { - let cli = Cli::parse(); - - let recovery_file = std::fs::read(&cli.recovery_file)?; - println!("\nSuccessfully opened recovery file"); - - let url = cli.url; - - let caps = url - .query_pairs() - .filter_map(|(key, value)| { - if key == "caps" { - return Some( - value - .split(',') - .filter_map(|cap| Capability::try_from(cap).ok()) - .collect::>(), - ); - }; - None - }) - .next() - .unwrap_or_default(); - - if !caps.is_empty() { - println!("\nRequired Capabilities:"); - } - - for cap in &caps { - println!(" {} : {:?}", cap.scope, cap.actions); - } - - // === Consent form === - - println!("\nEnter your recovery_file's passphrase to confirm:"); - let passphrase = rpassword::read_password()?; - - let keypair = pubky_common::recovery_file::decrypt_recovery_file(&recovery_file, &passphrase)?; - - println!("Successfully decrypted recovery file..."); - println!("PublicKey: {}", keypair.public_key()); - - let client = PubkyClient::testnet(); - - // For the purposes of this demo, we need to make sure - // the user has an account on the local homeserver. - if client.signin(&keypair).await.is_err() { - client - .signup(&keypair, &PublicKey::try_from(HOMESERVER).unwrap()) - .await?; - }; - - println!("Sending AuthToken to the 3rd party app..."); - - client.send_auth_token(&keypair, url).await?; - - Ok(()) -} diff --git a/rust/pubky/pubky-common/Cargo.toml b/rust/pubky/pubky-common/Cargo.toml deleted file mode 100644 index 9676fba..0000000 --- a/rust/pubky/pubky-common/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "pubky-common" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -base32 = "0.5.0" -blake3 = "1.5.1" -ed25519-dalek = "2.1.1" -once_cell = "1.19.0" -pkarr = { workspace = true } -rand = "0.8.5" -thiserror = "1.0.60" -postcard = { version = "1.0.8", features = ["alloc"] } -crypto_secretbox = { version = "0.1.1", features = ["std"] } -argon2 = { version = "0.5.3", features = ["std"] } - -serde = { workspace = true, optional = true } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -js-sys = "0.3.69" - -[dev-dependencies] -postcard = "1.0.8" - -[features] - -serde = ["dep:serde", "ed25519-dalek/serde", "pkarr/serde"] -full = ['serde'] - -default = ['full'] diff --git a/rust/pubky/pubky-common/src/auth.rs b/rust/pubky/pubky-common/src/auth.rs deleted file mode 100644 index 866fe5e..0000000 --- a/rust/pubky/pubky-common/src/auth.rs +++ /dev/null @@ -1,279 +0,0 @@ -//! Client-server Authentication using signed timesteps - -use std::sync::{Arc, Mutex}; - -use serde::{Deserialize, Serialize}; - -use crate::{ - capabilities::{Capabilities, Capability}, - crypto::{Keypair, PublicKey, Signature}, - namespaces::PUBKY_AUTH, - timestamp::Timestamp, -}; - -// 30 seconds -const TIME_INTERVAL: u64 = 30 * 1_000_000; - -const CURRENT_VERSION: u8 = 0; -// 45 seconds in the past or the future -const TIMESTAMP_WINDOW: i64 = 45 * 1_000_000; - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct AuthToken { - /// Signature over the token. - signature: Signature, - /// A namespace to ensure this signature can't be used for any - /// other purposes that share the same message structurea by accident. - namespace: [u8; 10], - /// Version of the [AuthToken], in case we need to upgrade it to support unforseen usecases. - /// - /// Version 0: - /// - Signer is implicitly the same as the root keypair for - /// the [AuthToken::pubky], without any delegation. - /// - Capabilities are only meant for resoucres on the homeserver. - version: u8, - /// Timestamp - timestamp: Timestamp, - /// The [PublicKey] of the owner of the resources being accessed by this token. - pubky: PublicKey, - // Variable length capabilities - capabilities: Capabilities, -} - -impl AuthToken { - pub fn sign(keypair: &Keypair, capabilities: impl Into) -> Self { - let timestamp = Timestamp::now(); - - let mut token = Self { - signature: Signature::from_bytes(&[0; 64]), - namespace: *PUBKY_AUTH, - version: 0, - timestamp, - pubky: keypair.public_key(), - capabilities: capabilities.into(), - }; - - let serialized = token.serialize(); - - token.signature = keypair.sign(&serialized[65..]); - - token - } - - pub fn capabilities(&self) -> &[Capability] { - &self.capabilities.0 - } - - pub fn verify(bytes: &[u8]) -> Result { - if bytes[75] > CURRENT_VERSION { - return Err(Error::UnknownVersion); - } - - let token = AuthToken::deserialize(bytes)?; - - match token.version { - 0 => { - let now = Timestamp::now(); - - // Chcek timestamp; - let diff = token.timestamp.difference(&now); - if diff > TIMESTAMP_WINDOW { - return Err(Error::TooFarInTheFuture); - } - if diff < -TIMESTAMP_WINDOW { - return Err(Error::Expired); - } - - token - .pubky - .verify(AuthToken::signable(token.version, bytes), &token.signature) - .map_err(|_| Error::InvalidSignature)?; - - Ok(token) - } - _ => unreachable!(), - } - } - - pub fn serialize(&self) -> Vec { - postcard::to_allocvec(self).unwrap() - } - - pub fn deserialize(bytes: &[u8]) -> Result { - Ok(postcard::from_bytes(bytes)?) - } - - pub fn pubky(&self) -> &PublicKey { - &self.pubky - } - - /// A unique ID for this [AuthToken], which is a concatenation of - /// [AuthToken::pubky] and [AuthToken::timestamp]. - /// - /// Assuming that [AuthToken::timestamp] is unique for every [AuthToken::pubky]. - fn id(version: u8, bytes: &[u8]) -> Box<[u8]> { - match version { - 0 => bytes[75..115].into(), - _ => unreachable!(), - } - } - - fn signable(version: u8, bytes: &[u8]) -> &[u8] { - match version { - 0 => bytes[65..].into(), - _ => unreachable!(), - } - } -} - -#[derive(Debug, Clone, Default)] -/// Keeps track of used AuthToken until they expire. -pub struct AuthVerifier { - seen: Arc>>>, -} - -impl AuthVerifier { - pub fn verify(&self, bytes: &[u8]) -> Result { - self.gc(); - - let token = AuthToken::verify(bytes)?; - - let mut seen = self.seen.lock().unwrap(); - - let id = AuthToken::id(token.version, bytes); - - match seen.binary_search_by(|element| element.cmp(&id)) { - Ok(_) => Err(Error::AlreadyUsed), - Err(index) => { - seen.insert(index, id); - Ok(token) - } - } - } - - // === Private Methods === - - /// Remove all tokens older than two time intervals in the past. - fn gc(&self) { - let threshold = ((Timestamp::now().into_inner() / TIME_INTERVAL) - 2).to_be_bytes(); - - let mut inner = self.seen.lock().unwrap(); - - match inner.binary_search_by(|element| element[0..8].cmp(&threshold)) { - Ok(index) | Err(index) => { - inner.drain(0..index); - } - } - } -} - -#[derive(thiserror::Error, Debug, PartialEq, Eq)] -pub enum Error { - #[error("Unknown version")] - UnknownVersion, - #[error("AuthToken has a timestamp that is more than 45 seconds in the future")] - TooFarInTheFuture, - #[error("AuthToken has a timestamp that is more than 45 seconds in the past")] - Expired, - #[error("Invalid Signature")] - InvalidSignature, - #[error(transparent)] - Postcard(#[from] postcard::Error), - #[error("AuthToken already used")] - AlreadyUsed, -} - -#[cfg(test)] -mod tests { - use crate::{ - auth::TIMESTAMP_WINDOW, capabilities::Capability, crypto::Keypair, timestamp::Timestamp, - }; - - use super::*; - - #[test] - fn v0_id_signable() { - let signer = Keypair::random(); - let capabilities = vec![Capability::root()]; - - let token = AuthToken::sign(&signer, capabilities.clone()); - - let serialized = &token.serialize(); - - let mut id = vec![]; - id.extend_from_slice(&token.timestamp.to_bytes()); - id.extend_from_slice(signer.public_key().as_bytes()); - - assert_eq!(AuthToken::id(token.version, serialized), id.into()); - - assert_eq!( - AuthToken::signable(token.version, serialized), - &serialized[65..] - ) - } - - #[test] - fn sign_verify() { - let signer = Keypair::random(); - let capabilities = vec![Capability::root()]; - - let verifier = AuthVerifier::default(); - - let token = AuthToken::sign(&signer, capabilities.clone()); - - let serialized = &token.serialize(); - - verifier.verify(serialized).unwrap(); - - assert_eq!(token.capabilities, capabilities.into()); - } - - #[test] - fn expired() { - let signer = Keypair::random(); - let capabilities = Capabilities(vec![Capability::root()]); - - let verifier = AuthVerifier::default(); - - let timestamp = (&Timestamp::now()) - (TIMESTAMP_WINDOW as u64); - - let mut signable = vec![]; - signable.extend_from_slice(signer.public_key().as_bytes()); - signable.extend_from_slice(&postcard::to_allocvec(&capabilities).unwrap()); - - let signature = signer.sign(&signable); - - let token = AuthToken { - signature, - namespace: *PUBKY_AUTH, - version: 0, - timestamp, - pubky: signer.public_key(), - capabilities, - }; - - let serialized = token.serialize(); - - let result = verifier.verify(&serialized); - - assert_eq!(result, Err(Error::Expired)); - } - - #[test] - fn already_used() { - let signer = Keypair::random(); - let capabilities = vec![Capability::root()]; - - let verifier = AuthVerifier::default(); - - let token = AuthToken::sign(&signer, capabilities.clone()); - - let serialized = &token.serialize(); - - verifier.verify(serialized).unwrap(); - - assert_eq!(token.capabilities, capabilities.into()); - - assert_eq!(verifier.verify(serialized), Err(Error::AlreadyUsed)); - } -} diff --git a/rust/pubky/pubky-common/src/capabilities.rs b/rust/pubky/pubky-common/src/capabilities.rs deleted file mode 100644 index 7929860..0000000 --- a/rust/pubky/pubky-common/src/capabilities.rs +++ /dev/null @@ -1,237 +0,0 @@ -use std::fmt::Display; - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Capability { - pub scope: String, - pub actions: Vec, -} - -impl Capability { - /// Create a root [Capability] at the `/` path with all the available [PubkyAbility] - pub fn root() -> Self { - Capability { - scope: "/".to_string(), - actions: vec![Action::Read, Action::Write], - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Action { - /// Can read the scope at the specified path (GET requests). - Read, - /// Can write to the scope at the specified path (PUT/POST/DELETE requests). - Write, - /// Unknown ability - Unknown(char), -} - -impl From<&Action> for char { - fn from(value: &Action) -> Self { - match value { - Action::Read => 'r', - Action::Write => 'w', - Action::Unknown(char) => char.to_owned(), - } - } -} - -impl TryFrom for Action { - type Error = Error; - - fn try_from(value: char) -> Result { - match value { - 'r' => Ok(Self::Read), - 'w' => Ok(Self::Write), - _ => Err(Error::InvalidAction), - } - } -} - -impl Display for Capability { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}:{}", - self.scope, - self.actions.iter().map(char::from).collect::() - ) - } -} - -impl TryFrom for Capability { - type Error = Error; - - fn try_from(value: String) -> Result { - value.as_str().try_into() - } -} - -impl TryFrom<&str> for Capability { - type Error = Error; - - fn try_from(value: &str) -> Result { - if value.matches(':').count() != 1 { - return Err(Error::InvalidFormat); - } - - if !value.starts_with('/') { - return Err(Error::InvalidScope); - } - - let actions_str = value.rsplit(':').next().unwrap_or(""); - - let mut actions = Vec::new(); - - for char in actions_str.chars() { - let ability = Action::try_from(char)?; - - match actions.binary_search_by(|element| char::from(element).cmp(&char)) { - Ok(_) => {} - Err(index) => { - actions.insert(index, ability); - } - } - } - - let scope = value[0..value.len() - actions_str.len() - 1].to_string(); - - Ok(Capability { scope, actions }) - } -} - -impl Serialize for Capability { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let string = self.to_string(); - - string.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for Capability { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let string: String = Deserialize::deserialize(deserializer)?; - - string.try_into().map_err(serde::de::Error::custom) - } -} - -#[derive(thiserror::Error, Debug, PartialEq, Eq)] -pub enum Error { - #[error("Capability: Invalid scope: does not start with `/`")] - InvalidScope, - #[error("Capability: Invalid format should be :")] - InvalidFormat, - #[error("Capability: Invalid Action")] - InvalidAction, - #[error("Capabilities: Invalid capabilities format")] - InvalidCapabilities, -} - -#[derive(Clone, Default, Debug, PartialEq, Eq)] -/// A wrapper around `Vec` to enable serialization without -/// a varint. Useful when [Capabilities] are at the end of a struct. -pub struct Capabilities(pub Vec); - -impl Capabilities { - pub fn contains(&self, capability: &Capability) -> bool { - self.0.contains(capability) - } -} - -impl From> for Capabilities { - fn from(value: Vec) -> Self { - Self(value) - } -} - -impl From for Vec { - fn from(value: Capabilities) -> Self { - value.0 - } -} - -impl TryFrom<&str> for Capabilities { - type Error = Error; - - fn try_from(value: &str) -> Result { - let mut caps = vec![]; - - for s in value.split(',') { - if let Ok(cap) = Capability::try_from(s) { - caps.push(cap); - }; - } - - Ok(Capabilities(caps)) - } -} - -impl Display for Capabilities { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let string = self - .0 - .iter() - .map(|c| c.to_string()) - .collect::>() - .join(","); - - write!(f, "{}", string) - } -} - -impl Serialize for Capabilities { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.to_string().serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for Capabilities { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let string: String = Deserialize::deserialize(deserializer)?; - - let mut caps = vec![]; - - for s in string.split(',') { - if let Ok(cap) = Capability::try_from(s) { - caps.push(cap); - }; - } - - Ok(Capabilities(caps)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn pubky_caps() { - let cap = Capability { - scope: "/pub/pubky.app/".to_string(), - actions: vec![Action::Read, Action::Write], - }; - - // Read and write withing directory `/pub/pubky.app/`. - let expected_string = "/pub/pubky.app/:rw"; - - assert_eq!(cap.to_string(), expected_string); - - assert_eq!(Capability::try_from(expected_string), Ok(cap)) - } -} diff --git a/rust/pubky/pubky-common/src/crypto.rs b/rust/pubky/pubky-common/src/crypto.rs deleted file mode 100644 index a7adea5..0000000 --- a/rust/pubky/pubky-common/src/crypto.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crypto_secretbox::{ - aead::{Aead, AeadCore, KeyInit, OsRng}, - XSalsa20Poly1305, -}; -use rand::prelude::Rng; - -pub use pkarr::{Keypair, PublicKey}; - -pub use ed25519_dalek::Signature; - -pub type Hash = blake3::Hash; - -pub use blake3::hash; - -pub use blake3::Hasher; - -pub fn random_hash() -> Hash { - let mut rng = rand::thread_rng(); - Hash::from_bytes(rng.gen()) -} - -pub fn random_bytes() -> [u8; N] { - let mut rng = rand::thread_rng(); - let mut arr = [0u8; N]; - - #[allow(clippy::needless_range_loop)] - for i in 0..N { - arr[i] = rng.gen(); - } - arr -} - -pub fn encrypt(plain_text: &[u8], encryption_key: &[u8; 32]) -> Result, Error> { - let cipher = XSalsa20Poly1305::new(encryption_key.into()); - let nonce = XSalsa20Poly1305::generate_nonce(&mut OsRng); // unique per message - let ciphertext = cipher.encrypt(&nonce, plain_text)?; - - let mut out: Vec = Vec::with_capacity(nonce.len() + ciphertext.len()); - out.extend_from_slice(nonce.as_slice()); - out.extend_from_slice(&ciphertext); - - Ok(out) -} - -pub fn decrypt(bytes: &[u8], encryption_key: &[u8; 32]) -> Result, Error> { - let cipher = XSalsa20Poly1305::new(encryption_key.into()); - - Ok(cipher.decrypt(bytes[..24].into(), &bytes[24..])?) -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - SecretBox(#[from] crypto_secretbox::Error), -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn encrypt_decrypt() { - let plain_text = "Plain text!"; - let encryption_key = [0; 32]; - - let encrypted = encrypt(plain_text.as_bytes(), &encryption_key).unwrap(); - let decrypted = decrypt(&encrypted, &encryption_key).unwrap(); - - assert_eq!(decrypted, plain_text.as_bytes()) - } -} diff --git a/rust/pubky/pubky-common/src/lib.rs b/rust/pubky/pubky-common/src/lib.rs deleted file mode 100644 index cfb56f2..0000000 --- a/rust/pubky/pubky-common/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod auth; -pub mod capabilities; -pub mod crypto; -pub mod namespaces; -pub mod recovery_file; -pub mod session; -pub mod timestamp; diff --git a/rust/pubky/pubky-common/src/namespaces.rs b/rust/pubky/pubky-common/src/namespaces.rs deleted file mode 100644 index 6aa37cd..0000000 --- a/rust/pubky/pubky-common/src/namespaces.rs +++ /dev/null @@ -1 +0,0 @@ -pub const PUBKY_AUTH: &[u8; 10] = b"PUBKY:AUTH"; diff --git a/rust/pubky/pubky-common/src/recovery_file.rs b/rust/pubky/pubky-common/src/recovery_file.rs deleted file mode 100644 index 0a2f9b4..0000000 --- a/rust/pubky/pubky-common/src/recovery_file.rs +++ /dev/null @@ -1,102 +0,0 @@ -use argon2::Argon2; -use pkarr::Keypair; - -use crate::crypto::{decrypt, encrypt}; - -static SPEC_NAME: &str = "recovery"; -static SPEC_LINE: &str = "pubky.org/recovery"; - -pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result { - let encryption_key = recovery_file_encryption_key_from_passphrase(passphrase)?; - - let newline_index = recovery_file - .iter() - .position(|&r| r == 10) - .ok_or(()) - .map_err(|_| Error::RecoveryFileMissingSpecLine)?; - - let spec_line = &recovery_file[..newline_index]; - - if !(spec_line.starts_with(SPEC_LINE.as_bytes()) - || spec_line.starts_with(b"pkarr.org/recovery")) - { - return Err(Error::RecoveryFileVersionNotSupported); - } - - let encrypted = &recovery_file[newline_index + 1..]; - - if encrypted.is_empty() { - return Err(Error::RecoverFileMissingEncryptedSecretKey); - }; - - let decrypted = decrypt(encrypted, &encryption_key)?; - let length = decrypted.len(); - let secret_key: [u8; 32] = decrypted - .try_into() - .map_err(|_| Error::RecoverFileInvalidSecretKeyLength(length))?; - - Ok(Keypair::from_secret_key(&secret_key)) -} - -pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result, Error> { - let encryption_key = recovery_file_encryption_key_from_passphrase(passphrase)?; - let secret_key = keypair.secret_key(); - - let encrypted_secret_key = encrypt(&secret_key, &encryption_key)?; - - let mut out = Vec::with_capacity(SPEC_LINE.len() + 1 + encrypted_secret_key.len()); - - out.extend_from_slice(SPEC_LINE.as_bytes()); - out.extend_from_slice(b"\n"); - out.extend_from_slice(&encrypted_secret_key); - - Ok(out) -} - -fn recovery_file_encryption_key_from_passphrase(passphrase: &str) -> Result<[u8; 32], Error> { - let argon2id = Argon2::default(); - - let mut out = [0; 32]; - - argon2id.hash_password_into(passphrase.as_bytes(), SPEC_NAME.as_bytes(), &mut out)?; - - Ok(out) -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - // === Recovery file == - #[error("Recovery file should start with a spec line, followed by a new line character")] - RecoveryFileMissingSpecLine, - - #[error("Recovery file should start with a spec line, followed by a new line character")] - RecoveryFileVersionNotSupported, - - #[error("Recovery file should contain an encrypted secret key after the new line character")] - RecoverFileMissingEncryptedSecretKey, - - #[error("Recovery file encrypted secret key should be 32 bytes, got {0}")] - RecoverFileInvalidSecretKeyLength(usize), - - #[error(transparent)] - Argon(#[from] argon2::Error), - - #[error(transparent)] - Crypto(#[from] crate::crypto::Error), -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn encrypt_decrypt_recovery_file() { - let passphrase = "very secure password"; - let keypair = Keypair::random(); - - let recovery_file = create_recovery_file(&keypair, passphrase).unwrap(); - let recovered = decrypt_recovery_file(&recovery_file, passphrase).unwrap(); - - assert_eq!(recovered.public_key(), keypair.public_key()); - } -} diff --git a/rust/pubky/pubky-common/src/session.rs b/rust/pubky/pubky-common/src/session.rs deleted file mode 100644 index 972652c..0000000 --- a/rust/pubky/pubky-common/src/session.rs +++ /dev/null @@ -1,139 +0,0 @@ -use pkarr::PublicKey; -use postcard::{from_bytes, to_allocvec}; -use serde::{Deserialize, Serialize}; - -extern crate alloc; -use alloc::vec::Vec; - -use crate::{auth::AuthToken, capabilities::Capability, timestamp::Timestamp}; - -// TODO: add IP address? -// TODO: use https://crates.io/crates/user-agent-parser to parse the session -// and get more informations from the user-agent. -#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct Session { - version: usize, - pubky: PublicKey, - created_at: u64, - /// User specified name, defaults to the user-agent. - name: String, - user_agent: String, - capabilities: Vec, -} - -impl Session { - pub fn new(token: &AuthToken, user_agent: Option) -> Self { - Self { - version: 0, - pubky: token.pubky().to_owned(), - created_at: Timestamp::now().into_inner(), - capabilities: token.capabilities().to_vec(), - user_agent: user_agent.as_deref().unwrap_or("").to_string(), - name: user_agent.as_deref().unwrap_or("").to_string(), - } - } - - // === Getters === - - pub fn pubky(&self) -> &PublicKey { - &self.pubky - } - - pub fn capabilities(&self) -> &Vec { - &self.capabilities - } - - // === Setters === - - pub fn set_user_agent(&mut self, user_agent: String) -> &mut Self { - self.user_agent = user_agent; - - if self.name.is_empty() { - self.name.clone_from(&self.user_agent) - } - - self - } - - pub fn set_capabilities(&mut self, capabilities: Vec) -> &mut Self { - self.capabilities = capabilities; - - self - } - - // === Public Methods === - - pub fn serialize(&self) -> Vec { - to_allocvec(self).expect("Session::serialize") - } - - pub fn deserialize(bytes: &[u8]) -> Result { - if bytes.is_empty() { - return Err(Error::EmptyPayload); - } - - if bytes[0] > 0 { - return Err(Error::UnknownVersion); - } - - Ok(from_bytes(bytes)?) - } - - // TODO: add `can_read()`, `can_write()` and `is_root()` methods -} - -pub type Result = core::result::Result; - -#[derive(thiserror::Error, Debug, PartialEq)] -pub enum Error { - #[error("Empty payload")] - EmptyPayload, - #[error("Unknown version")] - UnknownVersion, - #[error(transparent)] - Postcard(#[from] postcard::Error), -} - -#[cfg(test)] -mod tests { - use crate::crypto::Keypair; - - use super::*; - - #[test] - fn serialize() { - let keypair = Keypair::from_secret_key(&[0; 32]); - let pubky = keypair.public_key(); - - let session = Session { - user_agent: "foo".to_string(), - capabilities: vec![Capability::root()], - created_at: 0, - pubky, - version: 0, - name: "".to_string(), - }; - - let serialized = session.serialize(); - - assert_eq!( - serialized, - [ - 0, 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101, - 50, 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41, 0, 0, 3, 102, - 111, 111, 1, 4, 47, 58, 114, 119 - ] - ); - - let deseiralized = Session::deserialize(&serialized).unwrap(); - - assert_eq!(deseiralized, session) - } - - #[test] - fn deserialize() { - let result = Session::deserialize(&[]); - - assert_eq!(result, Err(Error::EmptyPayload)); - } -} diff --git a/rust/pubky/pubky-common/src/timestamp.rs b/rust/pubky/pubky-common/src/timestamp.rs deleted file mode 100644 index c3c9846..0000000 --- a/rust/pubky/pubky-common/src/timestamp.rs +++ /dev/null @@ -1,280 +0,0 @@ -//! Strictly monotonic unix timestamp in microseconds - -use serde::{Deserialize, Serialize}; -use std::fmt::Display; -use std::{ - ops::{Add, Sub}, - sync::Mutex, -}; - -use once_cell::sync::Lazy; -use rand::Rng; - -#[cfg(not(target_arch = "wasm32"))] -use std::time::SystemTime; - -/// ~4% chance of none of 10 clocks have matching id. -const CLOCK_MASK: u64 = (1 << 8) - 1; -const TIME_MASK: u64 = !0 >> 8; - -pub struct TimestampFactory { - clock_id: u64, - last_time: u64, -} - -impl TimestampFactory { - pub fn new() -> Self { - Self { - clock_id: rand::thread_rng().gen::() & CLOCK_MASK, - last_time: system_time() & TIME_MASK, - } - } - - pub fn now(&mut self) -> Timestamp { - // Ensure strict monotonicity. - self.last_time = (system_time() & TIME_MASK).max(self.last_time + CLOCK_MASK + 1); - - // Add clock_id to the end of the timestamp - Timestamp(self.last_time | self.clock_id) - } -} - -impl Default for TimestampFactory { - fn default() -> Self { - Self::new() - } -} - -static DEFAULT_FACTORY: Lazy> = - Lazy::new(|| Mutex::new(TimestampFactory::default())); - -/// STrictly monotonic timestamp since [SystemTime::UNIX_EPOCH] in microseconds as u64. -/// -/// The purpose of this timestamp is to unique per "user", not globally, -/// it achieves this by: -/// 1. Override the last byte with a random `clock_id`, reducing the probability -/// of two matching timestamps across multiple machines/threads. -/// 2. Gurantee that the remaining 3 bytes are ever increasing (strictly monotonic) within -/// the same thread regardless of the wall clock value -/// -/// This timestamp is also serialized as BE bytes to remain sortable. -/// If a `utf-8` encoding is necessary, it is encoded as [base32::Alphabet::Crockford] -/// to act as a sortable Id. -/// -/// U64 of microseconds is valid for the next 500 thousand years! -#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)] -pub struct Timestamp(u64); - -impl Timestamp { - pub fn now() -> Self { - DEFAULT_FACTORY.lock().unwrap().now() - } - - /// Return big endian bytes - pub fn to_bytes(&self) -> [u8; 8] { - self.0.to_be_bytes() - } - - pub fn difference(&self, rhs: &Timestamp) -> i64 { - (self.0 as i64) - (rhs.0 as i64) - } - - pub fn into_inner(&self) -> u64 { - self.0 - } -} - -impl Default for Timestamp { - fn default() -> Self { - Timestamp::now() - } -} - -impl Display for Timestamp { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let bytes: [u8; 8] = self.into(); - f.write_str(&base32::encode(base32::Alphabet::Crockford, &bytes)) - } -} - -impl TryFrom for Timestamp { - type Error = TimestampError; - - fn try_from(value: String) -> Result { - match base32::decode(base32::Alphabet::Crockford, &value) { - Some(vec) => { - let bytes: [u8; 8] = vec - .try_into() - .map_err(|_| TimestampError::InvalidEncoding)?; - - Ok(bytes.into()) - } - None => Err(TimestampError::InvalidEncoding), - } - } -} - -impl TryFrom<&[u8]> for Timestamp { - type Error = TimestampError; - - fn try_from(bytes: &[u8]) -> Result { - let bytes: [u8; 8] = bytes - .try_into() - .map_err(|_| TimestampError::InvalidBytesLength(bytes.len()))?; - - Ok(bytes.into()) - } -} - -impl From<&Timestamp> for [u8; 8] { - fn from(timestamp: &Timestamp) -> Self { - timestamp.0.to_be_bytes() - } -} - -impl From<[u8; 8]> for Timestamp { - fn from(bytes: [u8; 8]) -> Self { - Self(u64::from_be_bytes(bytes)) - } -} - -// === U64 conversion === - -impl From for u64 { - fn from(value: Timestamp) -> Self { - value.into_inner() - } -} - -impl Add for &Timestamp { - type Output = Timestamp; - - fn add(self, rhs: u64) -> Self::Output { - Timestamp(self.0 + rhs) - } -} - -impl Sub for &Timestamp { - type Output = Timestamp; - - fn sub(self, rhs: u64) -> Self::Output { - Timestamp(self.0 - rhs) - } -} - -impl Serialize for Timestamp { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let bytes = self.to_bytes(); - bytes.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for Timestamp { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes: [u8; 8] = Deserialize::deserialize(deserializer)?; - Ok(Timestamp(u64::from_be_bytes(bytes))) - } -} - -#[cfg(not(target_arch = "wasm32"))] -/// Return the number of microseconds since [SystemTime::UNIX_EPOCH] -fn system_time() -> u64 { - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("time drift") - .as_micros() as u64 -} - -#[cfg(target_arch = "wasm32")] -/// Return the number of microseconds since [SystemTime::UNIX_EPOCH] -pub fn system_time() -> u64 { - // Won't be an issue for more than 5000 years! - (js_sys::Date::now() as u64 ) - // Turn miliseconds to microseconds - * 1000 -} - -#[derive(thiserror::Error, Debug)] -pub enum TimestampError { - #[error("Invalid bytes length, Timestamp should be encoded as 8 bytes, got {0}")] - InvalidBytesLength(usize), - #[error("Invalid timestamp encoding")] - InvalidEncoding, -} - -#[cfg(test)] -mod tests { - use std::collections::HashSet; - - use super::*; - - #[test] - fn strictly_monotonic() { - const COUNT: usize = 100; - - let mut set = HashSet::with_capacity(COUNT); - let mut vec = Vec::with_capacity(COUNT); - - for _ in 0..COUNT { - let timestamp = Timestamp::now(); - - set.insert(timestamp.clone()); - vec.push(timestamp); - } - - let mut ordered = vec.clone(); - ordered.sort(); - - assert_eq!(set.len(), COUNT, "unique"); - assert_eq!(ordered, vec, "ordered"); - } - - #[test] - fn strings() { - const COUNT: usize = 100; - - let mut set = HashSet::with_capacity(COUNT); - let mut vec = Vec::with_capacity(COUNT); - - for _ in 0..COUNT { - let string = Timestamp::now().to_string(); - - set.insert(string.clone()); - vec.push(string) - } - - let mut ordered = vec.clone(); - ordered.sort(); - - assert_eq!(set.len(), COUNT, "unique"); - assert_eq!(ordered, vec, "ordered"); - } - - #[test] - fn to_from_string() { - let timestamp = Timestamp::now(); - let string = timestamp.to_string(); - let decoded: Timestamp = string.try_into().unwrap(); - - assert_eq!(decoded, timestamp) - } - - #[test] - fn serde() { - let timestamp = Timestamp::now(); - - let serialized = postcard::to_allocvec(×tamp).unwrap(); - - assert_eq!(serialized, timestamp.to_bytes()); - - let deserialized: Timestamp = postcard::from_bytes(&serialized).unwrap(); - - assert_eq!(deserialized, timestamp); - } -} diff --git a/rust/pubky/pubky-homeserver/Cargo.toml b/rust/pubky/pubky-homeserver/Cargo.toml deleted file mode 100644 index c8abfd5..0000000 --- a/rust/pubky/pubky-homeserver/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "pubky_homeserver" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0.82" -axum = { version = "0.7.5", features = ["macros"] } -axum-extra = { version = "0.9.3", features = ["typed-header", "async-read-body"] } -base32 = "0.5.1" -bytes = "^1.7.1" -clap = { version = "4.5.11", features = ["derive"] } -dirs-next = "2.0.0" -flume = "0.11.0" -futures-util = "0.3.30" -heed = "0.20.3" -hex = "0.4.3" -pkarr = { workspace = true } -postcard = { version = "1.0.8", features = ["alloc"] } -pubky-common = { version = "0.1.0", path = "../pubky-common" } -serde = { workspace = true } -tokio = { version = "1.37.0", features = ["full"] } -toml = "0.8.19" -tower-cookies = "0.10.0" -tower-http = { version = "0.5.2", features = ["cors", "trace"] } -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/rust/pubky/pubky-homeserver/README.md b/rust/pubky/pubky-homeserver/README.md deleted file mode 100644 index d1799a2..0000000 --- a/rust/pubky/pubky-homeserver/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Pubky Homeserver - -## Usage - -Use `cargo run` - -```bash -cargo run -- --config=./src/config.toml -``` - -Or Build first then run from target. - -Build - -```bash -cargo build --release -``` - -Run with an optional config file - -```bash -../target/release/pubky-homeserver --config=./src/config.toml -``` diff --git a/rust/pubky/pubky-homeserver/src/config.rs b/rust/pubky/pubky-homeserver/src/config.rs deleted file mode 100644 index f182a52..0000000 --- a/rust/pubky/pubky-homeserver/src/config.rs +++ /dev/null @@ -1,248 +0,0 @@ -//! Configuration for the server - -use anyhow::{anyhow, Context, Result}; -use pkarr::Keypair; -use serde::{Deserialize, Serialize}; -use std::{ - fmt::Debug, - path::{Path, PathBuf}, - time::Duration, -}; -use tracing::info; - -use pubky_common::timestamp::Timestamp; - -const DEFAULT_HOMESERVER_PORT: u16 = 6287; -const DEFAULT_STORAGE_DIR: &str = "pubky"; - -pub const DEFAULT_LIST_LIMIT: u16 = 100; -pub const DEFAULT_MAX_LIST_LIMIT: u16 = 1000; - -#[derive(Serialize, Deserialize, Clone, PartialEq)] -struct ConfigToml { - testnet: Option, - port: Option, - bootstrap: Option>, - domain: Option, - storage: Option, - secret_key: Option, - dht_request_timeout: Option, - default_list_limit: Option, - max_list_limit: Option, -} - -/// Server configuration -#[derive(Debug, Clone)] -pub struct Config { - /// Whether or not this server is running in a testnet. - testnet: bool, - /// The configured port for this server. - port: Option, - /// Bootstrapping DHT nodes. - /// - /// Helpful to run the server locally or in testnet. - bootstrap: Option>, - /// A public domain for this server - /// necessary for web browsers running in https environment. - domain: Option, - /// Path to the storage directory. - /// - /// Defaults to a directory in the OS data directory - storage: PathBuf, - /// Server keypair. - /// - /// Defaults to a random keypair. - keypair: Keypair, - dht_request_timeout: Option, - /// The default limit of a list api if no `limit` query parameter is provided. - /// - /// Defaults to `100` - default_list_limit: u16, - /// The maximum limit of a list api, even if a `limit` query parameter is provided. - /// - /// Defaults to `1000` - max_list_limit: u16, -} - -impl Config { - fn try_from_str(value: &str) -> Result { - let config_toml: ConfigToml = toml::from_str(value)?; - - let keypair = if let Some(secret_key) = config_toml.secret_key { - let secret_key = deserialize_secret_key(secret_key)?; - Keypair::from_secret_key(&secret_key) - } else { - Keypair::random() - }; - - let storage = { - let dir = if let Some(storage) = config_toml.storage { - storage - } else { - let path = dirs_next::data_dir().ok_or_else(|| { - anyhow!("operating environment provides no directory for application data") - })?; - path.join(DEFAULT_STORAGE_DIR) - }; - - dir.join("homeserver") - }; - - let config = Config { - testnet: config_toml.testnet.unwrap_or(false), - port: config_toml.port, - bootstrap: config_toml.bootstrap, - domain: config_toml.domain, - keypair, - storage, - dht_request_timeout: config_toml.dht_request_timeout, - default_list_limit: config_toml.default_list_limit.unwrap_or(DEFAULT_LIST_LIMIT), - max_list_limit: config_toml - .default_list_limit - .unwrap_or(DEFAULT_MAX_LIST_LIMIT), - }; - - if config.testnet { - let testnet_config = Config::testnet(); - - return Ok(Config { - bootstrap: testnet_config.bootstrap, - ..config - }); - } - - Ok(config) - } - - /// Load the config from a file. - pub async fn load(path: impl AsRef) -> Result { - let s = tokio::fs::read_to_string(path.as_ref()) - .await - .with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?; - - Config::try_from_str(&s) - } - - /// Testnet configurations - pub fn testnet() -> Self { - let testnet = pkarr::mainline::Testnet::new(10); - info!(?testnet.bootstrap, "Testnet bootstrap nodes"); - - let bootstrap = Some(testnet.bootstrap.to_owned()); - let storage = std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join(DEFAULT_STORAGE_DIR); - - Self { - bootstrap, - storage, - port: Some(15411), - dht_request_timeout: Some(Duration::from_millis(10)), - ..Default::default() - } - } - - /// Test configurations - pub fn test(testnet: &pkarr::mainline::Testnet) -> Self { - let bootstrap = Some(testnet.bootstrap.to_owned()); - let storage = std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join(DEFAULT_STORAGE_DIR); - - Self { - bootstrap, - storage, - ..Default::default() - } - } - - pub fn port(&self) -> u16 { - self.port.unwrap_or(DEFAULT_HOMESERVER_PORT) - } - - pub fn bootstsrap(&self) -> Option> { - self.bootstrap.to_owned() - } - - pub fn domain(&self) -> &Option { - &self.domain - } - - pub fn keypair(&self) -> &Keypair { - &self.keypair - } - - pub fn default_list_limit(&self) -> u16 { - self.default_list_limit - } - - pub fn max_list_limit(&self) -> u16 { - self.max_list_limit - } - - /// Get the path to the storage directory - pub fn storage(&self) -> &PathBuf { - &self.storage - } - - pub(crate) fn dht_request_timeout(&self) -> Option { - self.dht_request_timeout - } -} - -impl Default for Config { - fn default() -> Self { - Self { - testnet: false, - port: Some(0), - bootstrap: None, - domain: None, - storage: storage(None) - .expect("operating environment provides no directory for application data"), - keypair: Keypair::random(), - dht_request_timeout: None, - default_list_limit: DEFAULT_LIST_LIMIT, - max_list_limit: DEFAULT_MAX_LIST_LIMIT, - } - } -} - -fn deserialize_secret_key(s: String) -> anyhow::Result<[u8; 32]> { - let bytes = - hex::decode(s).map_err(|_| anyhow!("secret_key in config.toml should hex encoded"))?; - - if bytes.len() != 32 { - return Err(anyhow!(format!( - "secret_key in config.toml should be 32 bytes in hex (64 characters), got: {}", - bytes.len() - ))); - } - - let mut arr = [0u8; 32]; - arr.copy_from_slice(&bytes); - - Ok(arr) -} - -fn storage(storage: Option) -> Result { - let dir = if let Some(storage) = storage { - PathBuf::from(storage) - } else { - let path = dirs_next::data_dir().ok_or_else(|| { - anyhow!("operating environment provides no directory for application data") - })?; - path.join(DEFAULT_STORAGE_DIR) - }; - - Ok(dir.join("homeserver")) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_empty() { - Config::try_from_str("").unwrap(); - } -} diff --git a/rust/pubky/pubky-homeserver/src/config.toml b/rust/pubky/pubky-homeserver/src/config.toml deleted file mode 100644 index cb65622..0000000 --- a/rust/pubky/pubky-homeserver/src/config.toml +++ /dev/null @@ -1,10 +0,0 @@ -# Use testnet network (local DHT) for testing. -testnet = true -# Secret key (in hex) to generate the Homeserver's Keypair -secret_key = "0000000000000000000000000000000000000000000000000000000000000000" -# Domain to be published in Pkarr records for this server to be accessible by. -domain = "localhost" -# Port for the Homeserver to listen on. -port = 6287 -# Storage directory Defaults to -# storage = "" diff --git a/rust/pubky/pubky-homeserver/src/database.rs b/rust/pubky/pubky-homeserver/src/database.rs deleted file mode 100644 index ef82d0b..0000000 --- a/rust/pubky/pubky-homeserver/src/database.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::fs; - -use heed::{Env, EnvOpenOptions}; - -mod migrations; -pub mod tables; - -use crate::config::Config; - -use tables::{Tables, TABLES_COUNT}; - -pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) - -#[derive(Debug, Clone)] -pub struct DB { - pub(crate) env: Env, - pub(crate) tables: Tables, - pub(crate) config: Config, -} - -impl DB { - pub fn open(config: Config) -> anyhow::Result { - fs::create_dir_all(config.storage())?; - - let env = unsafe { - EnvOpenOptions::new() - .max_dbs(TABLES_COUNT) - // TODO: Add a configuration option? - .map_size(DEFAULT_MAP_SIZE) - .open(config.storage()) - }?; - - let tables = migrations::run(&env)?; - - let db = DB { - env, - tables, - config, - }; - - Ok(db) - } -} - -#[cfg(test)] -mod tests { - use bytes::Bytes; - use pkarr::{mainline::Testnet, Keypair}; - - use crate::config::Config; - - use super::DB; - - #[tokio::test] - async fn entries() { - let db = DB::open(Config::test(&Testnet::new(0))).unwrap(); - - let keypair = Keypair::random(); - let path = "/pub/foo.txt"; - - let (tx, rx) = flume::bounded::(0); - - let mut cloned = db.clone(); - let cloned_keypair = keypair.clone(); - - let done = tokio::task::spawn_blocking(move || { - cloned - .put_entry(&cloned_keypair.public_key(), path, rx) - .unwrap(); - }); - - tx.send(vec![1, 2, 3, 4, 5].into()).unwrap(); - drop(tx); - - done.await.unwrap(); - - let blob = db.get_blob(&keypair.public_key(), path).unwrap().unwrap(); - - assert_eq!(blob, Bytes::from(vec![1, 2, 3, 4, 5])); - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/migrations.rs b/rust/pubky/pubky-homeserver/src/database/migrations.rs deleted file mode 100644 index eb5a5f8..0000000 --- a/rust/pubky/pubky-homeserver/src/database/migrations.rs +++ /dev/null @@ -1,17 +0,0 @@ -use heed::Env; - -mod m0; - -use super::tables::Tables; - -pub fn run(env: &Env) -> anyhow::Result { - let mut wtxn = env.write_txn()?; - - m0::run(env, &mut wtxn)?; - - let tables = Tables::new(env, &mut wtxn)?; - - wtxn.commit()?; - - Ok(tables) -} diff --git a/rust/pubky/pubky-homeserver/src/database/migrations/m0.rs b/rust/pubky/pubky-homeserver/src/database/migrations/m0.rs deleted file mode 100644 index 11c0e1a..0000000 --- a/rust/pubky/pubky-homeserver/src/database/migrations/m0.rs +++ /dev/null @@ -1,17 +0,0 @@ -use heed::{Env, RwTxn}; - -use crate::database::tables::{blobs, entries, events, sessions, users}; - -pub fn run(env: &Env, wtxn: &mut RwTxn) -> anyhow::Result<()> { - let _: users::UsersTable = env.create_database(wtxn, Some(users::USERS_TABLE))?; - - let _: sessions::SessionsTable = env.create_database(wtxn, Some(sessions::SESSIONS_TABLE))?; - - let _: blobs::BlobsTable = env.create_database(wtxn, Some(blobs::BLOBS_TABLE))?; - - let _: entries::EntriesTable = env.create_database(wtxn, Some(entries::ENTRIES_TABLE))?; - - let _: events::EventsTable = env.create_database(wtxn, Some(events::EVENTS_TABLE))?; - - Ok(()) -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables.rs b/rust/pubky/pubky-homeserver/src/database/tables.rs deleted file mode 100644 index e879bd0..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables.rs +++ /dev/null @@ -1,49 +0,0 @@ -pub mod blobs; -pub mod entries; -pub mod events; -pub mod sessions; -pub mod users; - -use heed::{Env, RwTxn}; - -use blobs::{BlobsTable, BLOBS_TABLE}; -use entries::{EntriesTable, ENTRIES_TABLE}; - -use self::{ - events::{EventsTable, EVENTS_TABLE}, - sessions::{SessionsTable, SESSIONS_TABLE}, - users::{UsersTable, USERS_TABLE}, -}; - -pub const TABLES_COUNT: u32 = 5; - -#[derive(Debug, Clone)] -pub struct Tables { - pub users: UsersTable, - pub sessions: SessionsTable, - pub blobs: BlobsTable, - pub entries: EntriesTable, - pub events: EventsTable, -} - -impl Tables { - pub fn new(env: &Env, wtxn: &mut RwTxn) -> anyhow::Result { - Ok(Self { - users: env - .open_database(wtxn, Some(USERS_TABLE))? - .expect("Users table already created"), - sessions: env - .open_database(wtxn, Some(SESSIONS_TABLE))? - .expect("Sessions table already created"), - blobs: env - .open_database(wtxn, Some(BLOBS_TABLE))? - .expect("Blobs table already created"), - entries: env - .open_database(wtxn, Some(ENTRIES_TABLE))? - .expect("Entries table already created"), - events: env - .open_database(wtxn, Some(EVENTS_TABLE))? - .expect("Events table already created"), - }) - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables/blobs.rs b/rust/pubky/pubky-homeserver/src/database/tables/blobs.rs deleted file mode 100644 index c430a58..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables/blobs.rs +++ /dev/null @@ -1,38 +0,0 @@ -use heed::{types::Bytes, Database}; -use pkarr::PublicKey; - -use crate::database::DB; - -use super::entries::Entry; - -/// hash of the blob => bytes. -pub type BlobsTable = Database; - -pub const BLOBS_TABLE: &str = "blobs"; - -impl DB { - pub fn get_blob( - &self, - public_key: &PublicKey, - path: &str, - ) -> anyhow::Result> { - let rtxn = self.env.read_txn()?; - - let key = format!("{public_key}/{path}"); - - let result = if let Some(bytes) = self.tables.entries.get(&rtxn, &key)? { - let entry = Entry::deserialize(bytes)?; - - self.tables - .blobs - .get(&rtxn, entry.content_hash())? - .map(|blob| bytes::Bytes::from(blob[8..].to_vec())) - } else { - None - }; - - rtxn.commit()?; - - Ok(result) - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables/entries.rs b/rust/pubky/pubky-homeserver/src/database/tables/entries.rs deleted file mode 100644 index b1c7039..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables/entries.rs +++ /dev/null @@ -1,315 +0,0 @@ -use pkarr::PublicKey; -use postcard::{from_bytes, to_allocvec}; -use serde::{Deserialize, Serialize}; -use tracing::instrument; - -use heed::{ - types::{Bytes, Str}, - Database, RoTxn, -}; - -use pubky_common::{ - crypto::{Hash, Hasher}, - timestamp::Timestamp, -}; - -use crate::database::DB; - -use super::events::Event; - -/// full_path(pubky/*path) => Entry. -pub type EntriesTable = Database; - -pub const ENTRIES_TABLE: &str = "entries"; - -impl DB { - pub fn put_entry( - &mut self, - public_key: &PublicKey, - path: &str, - rx: flume::Receiver, - ) -> anyhow::Result<()> { - let mut wtxn = self.env.write_txn()?; - - let mut hasher = Hasher::new(); - let mut bytes = vec![]; - let mut length = 0; - - while let Ok(chunk) = rx.recv() { - hasher.update(&chunk); - bytes.extend_from_slice(&chunk); - length += chunk.len(); - } - - let hash = hasher.finalize(); - - let key = hash.as_bytes(); - - let mut bytes_with_ref_count = Vec::with_capacity(bytes.len() + 8); - bytes_with_ref_count.extend_from_slice(&u64::to_be_bytes(0)); - bytes_with_ref_count.extend_from_slice(&bytes); - - // TODO: For now, we set the first 8 bytes to a reference counter - let exists = self - .tables - .blobs - .get(&wtxn, key)? - .unwrap_or(bytes_with_ref_count.as_slice()); - - let new_count = u64::from_be_bytes(exists[0..8].try_into().unwrap()) + 1; - - bytes_with_ref_count[0..8].copy_from_slice(&u64::to_be_bytes(new_count)); - - self.tables - .blobs - .put(&mut wtxn, hash.as_bytes(), &bytes_with_ref_count)?; - - let mut entry = Entry::new(); - - entry.set_content_hash(hash); - entry.set_content_length(length); - - let key = format!("{public_key}/{path}"); - - self.tables - .entries - .put(&mut wtxn, &key, &entry.serialize())?; - - if path.starts_with("pub/") { - let url = format!("pubky://{key}"); - let event = Event::put(&url); - let value = event.serialize(); - - let key = entry.timestamp.to_string(); - - self.tables.events.put(&mut wtxn, &key, &value)?; - - // TODO: delete older events. - // TODO: move to events.rs - } - - wtxn.commit()?; - - Ok(()) - } - - pub fn delete_entry(&mut self, public_key: &PublicKey, path: &str) -> anyhow::Result { - let mut wtxn = self.env.write_txn()?; - - let key = format!("{public_key}/{path}"); - - let deleted = if let Some(bytes) = self.tables.entries.get(&wtxn, &key)? { - let entry = Entry::deserialize(bytes)?; - - let mut bytes_with_ref_count = self - .tables - .blobs - .get(&wtxn, entry.content_hash())? - .map_or(vec![], |s| s.to_vec()); - - let arr: [u8; 8] = bytes_with_ref_count[0..8].try_into().unwrap_or([0; 8]); - let reference_count = u64::from_be_bytes(arr); - - let deleted_blobs = if reference_count > 1 { - // decrement reference count - - bytes_with_ref_count[0..8].copy_from_slice(&(reference_count - 1).to_be_bytes()); - - self.tables - .blobs - .put(&mut wtxn, entry.content_hash(), &bytes_with_ref_count)?; - - true - } else { - self.tables.blobs.delete(&mut wtxn, entry.content_hash())? - }; - - let deleted_entry = self.tables.entries.delete(&mut wtxn, &key)?; - - // create DELETE event - if path.starts_with("pub/") { - let url = format!("pubky://{key}"); - - let event = Event::delete(&url); - let value = event.serialize(); - - let key = Timestamp::now().to_string(); - - self.tables.events.put(&mut wtxn, &key, &value)?; - - // TODO: delete older events. - // TODO: move to events.rs - } - - deleted_entry && deleted_blobs - } else { - false - }; - - wtxn.commit()?; - - Ok(deleted) - } - - pub fn contains_directory(&self, txn: &RoTxn, path: &str) -> anyhow::Result { - Ok(self.tables.entries.get_greater_than(txn, path)?.is_some()) - } - - /// Return a list of pubky urls. - /// - /// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit] - pub fn list( - &self, - txn: &RoTxn, - path: &str, - reverse: bool, - limit: Option, - cursor: Option, - shallow: bool, - ) -> anyhow::Result> { - // Vector to store results - let mut results = Vec::new(); - - let limit = limit - .unwrap_or(self.config.default_list_limit()) - .min(self.config.max_list_limit()); - - // TODO: make this more performant than split and allocations? - - let mut threshold = cursor - .map(|cursor| { - // Removing leading forward slashes - let mut file_or_directory = cursor.trim_start_matches('/'); - - if cursor.starts_with("pubky://") { - file_or_directory = cursor.split(path).last().expect("should not be reachable") - }; - - next_threshold( - path, - file_or_directory, - file_or_directory.ends_with('/'), - reverse, - shallow, - ) - }) - .unwrap_or(next_threshold(path, "", false, reverse, shallow)); - - for _ in 0..limit { - if let Some((key, _)) = if reverse { - self.tables.entries.get_lower_than(txn, &threshold)? - } else { - self.tables.entries.get_greater_than(txn, &threshold)? - } { - if !key.starts_with(path) { - break; - } - - if shallow { - let mut split = key[path.len()..].split('/'); - let file_or_directory = split.next().expect("should not be reachable"); - - let is_directory = split.next().is_some(); - - threshold = - next_threshold(path, file_or_directory, is_directory, reverse, shallow); - - results.push(format!( - "pubky://{path}{file_or_directory}{}", - if is_directory { "/" } else { "" } - )); - } else { - threshold = key.to_string(); - results.push(format!("pubky://{}", key)) - } - }; - } - - Ok(results) - } -} - -/// Calculate the next threshold -#[instrument] -fn next_threshold( - path: &str, - file_or_directory: &str, - is_directory: bool, - reverse: bool, - shallow: bool, -) -> String { - format!( - "{path}{file_or_directory}{}", - if file_or_directory.is_empty() { - // No file_or_directory, early return - if reverse { - // `path/to/dir/\x7f` to catch all paths than `path/to/dir/` - "\x7f" - } else { - "" - } - } else if shallow & is_directory { - if reverse { - // threshold = `path/to/dir\x2e`, since `\x2e` is lower than `/` - "\x2e" - } else { - //threshold = `path/to/dir\x7f`, since `\x7f` is greater than `/` - "\x7f" - } - } else { - "" - } - ) -} - -#[derive(Clone, Default, Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct Entry { - /// Encoding version - version: usize, - /// Modified at - timestamp: Timestamp, - content_hash: [u8; 32], - content_length: usize, - content_type: String, - // user_metadata: ? -} - -// TODO: get headers like Etag - -impl Entry { - pub fn new() -> Self { - Default::default() - } - - // === Setters === - - pub fn set_content_hash(&mut self, content_hash: Hash) -> &mut Self { - content_hash.as_bytes().clone_into(&mut self.content_hash); - self - } - - pub fn set_content_length(&mut self, content_length: usize) -> &mut Self { - self.content_length = content_length; - self - } - - // === Getters === - - pub fn content_hash(&self) -> &[u8; 32] { - &self.content_hash - } - - // === Public Method === - - pub fn serialize(&self) -> Vec { - to_allocvec(self).expect("Session::serialize") - } - - pub fn deserialize(bytes: &[u8]) -> core::result::Result { - if bytes[0] > 0 { - panic!("Unknown Entry version"); - } - - from_bytes(bytes) - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables/events.rs b/rust/pubky/pubky-homeserver/src/database/tables/events.rs deleted file mode 100644 index 76a4d46..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables/events.rs +++ /dev/null @@ -1,105 +0,0 @@ -//! Server events (Put and Delete entries) -//! -//! Useful as a realtime sync with Indexers until -//! we implement more self-authenticated merkle data. - -use heed::{ - types::{Bytes, Str}, - Database, -}; -use postcard::{from_bytes, to_allocvec}; -use serde::{Deserialize, Serialize}; - -use crate::database::DB; - -/// Event [Timestamp] base32 => Encoded event. -pub type EventsTable = Database; - -pub const EVENTS_TABLE: &str = "events"; - -#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] -pub enum Event { - Put(String), - Delete(String), -} - -impl Event { - pub fn put(url: &str) -> Self { - Self::Put(url.to_string()) - } - - pub fn delete(url: &str) -> Self { - Self::Delete(url.to_string()) - } - - pub fn serialize(&self) -> Vec { - to_allocvec(self).expect("Session::serialize") - } - - pub fn deserialize(bytes: &[u8]) -> core::result::Result { - if bytes[0] > 1 { - panic!("Unknown Event version"); - } - - from_bytes(bytes) - } - - pub fn url(&self) -> &str { - match self { - Event::Put(url) => url, - Event::Delete(url) => url, - } - } - - pub fn operation(&self) -> &str { - match self { - Event::Put(_) => "PUT", - Event::Delete(_) => "DEL", - } - } -} - -impl DB { - /// Returns a list of events formatted as ` `. - /// - /// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit] - /// - cursor is a 13 character string encoding of a timestamp - pub fn list_events( - &self, - limit: Option, - cursor: Option, - ) -> anyhow::Result> { - let txn = self.env.read_txn()?; - - let limit = limit - .unwrap_or(self.config.default_list_limit()) - .min(self.config.max_list_limit()); - - let cursor = cursor.unwrap_or("0000000000000".to_string()); - - let mut result: Vec = vec![]; - let mut next_cursor = cursor.to_string(); - - for _ in 0..limit { - match self.tables.events.get_greater_than(&txn, &next_cursor)? { - Some((timestamp, event_bytes)) => { - let event = Event::deserialize(event_bytes)?; - - let line = format!("{} {}", event.operation(), event.url()); - next_cursor = timestamp.to_string(); - - result.push(line); - } - None => break, - }; - } - - if !result.is_empty() { - result.push(format!("cursor: {next_cursor}")) - } - - txn.commit()?; - - Ok(result) - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables/sessions.rs b/rust/pubky/pubky-homeserver/src/database/tables/sessions.rs deleted file mode 100644 index 4ecd228..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables/sessions.rs +++ /dev/null @@ -1,51 +0,0 @@ -use heed::{ - types::{Bytes, Str}, - Database, -}; -use pkarr::PublicKey; -use pubky_common::session::Session; -use tower_cookies::Cookies; - -use crate::database::DB; - -/// session secret => Session. -pub type SessionsTable = Database; - -pub const SESSIONS_TABLE: &str = "sessions"; - -impl DB { - pub fn get_session( - &mut self, - cookies: Cookies, - public_key: &PublicKey, - ) -> anyhow::Result> { - if let Some(bytes) = self.get_session_bytes(cookies, public_key)? { - return Ok(Some(Session::deserialize(&bytes)?)); - }; - - Ok(None) - } - - pub fn get_session_bytes( - &mut self, - cookies: Cookies, - public_key: &PublicKey, - ) -> anyhow::Result>> { - if let Some(cookie) = cookies.get(&public_key.to_string()) { - let rtxn = self.env.read_txn()?; - - let sessions: SessionsTable = self - .env - .open_database(&rtxn, Some(SESSIONS_TABLE))? - .expect("Session table already created"); - - let session = sessions.get(&rtxn, cookie.value())?.map(|s| s.to_vec()); - - rtxn.commit()?; - - return Ok(session); - }; - - Ok(None) - } -} diff --git a/rust/pubky/pubky-homeserver/src/database/tables/users.rs b/rust/pubky/pubky-homeserver/src/database/tables/users.rs deleted file mode 100644 index cf9b44e..0000000 --- a/rust/pubky/pubky-homeserver/src/database/tables/users.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::borrow::Cow; - -use postcard::{from_bytes, to_allocvec}; -use serde::{Deserialize, Serialize}; - -use heed::{BoxedError, BytesDecode, BytesEncode, Database}; -use pkarr::PublicKey; - -extern crate alloc; - -/// PublicKey => User. -pub type UsersTable = Database; - -pub const USERS_TABLE: &str = "users"; - -// TODO: add more adminstration metadata like quota, invitation links, etc.. -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct User { - pub created_at: u64, -} - -impl<'a> BytesEncode<'a> for User { - type EItem = Self; - - fn bytes_encode(user: &Self::EItem) -> Result, BoxedError> { - let vec = to_allocvec(user).unwrap(); - - Ok(Cow::Owned(vec)) - } -} - -impl<'a> BytesDecode<'a> for User { - type DItem = Self; - - fn bytes_decode(bytes: &'a [u8]) -> Result { - let user: User = from_bytes(bytes).unwrap(); - - Ok(user) - } -} - -pub struct PublicKeyCodec {} - -impl<'a> BytesEncode<'a> for PublicKeyCodec { - type EItem = PublicKey; - - fn bytes_encode(pubky: &Self::EItem) -> Result, BoxedError> { - Ok(Cow::Borrowed(pubky.as_bytes())) - } -} - -impl<'a> BytesDecode<'a> for PublicKeyCodec { - type DItem = PublicKey; - - fn bytes_decode(bytes: &'a [u8]) -> Result { - Ok(PublicKey::try_from(bytes)?) - } -} diff --git a/rust/pubky/pubky-homeserver/src/error.rs b/rust/pubky/pubky-homeserver/src/error.rs deleted file mode 100644 index 8aa58d2..0000000 --- a/rust/pubky/pubky-homeserver/src/error.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! Server error - -use axum::{ - extract::rejection::{ExtensionRejection, PathRejection, QueryRejection}, - http::StatusCode, - response::IntoResponse, -}; -use tracing::debug; - -pub type Result = core::result::Result; - -#[derive(Debug, Clone)] -pub struct Error { - // #[serde(with = "serde_status_code")] - status: StatusCode, - detail: Option, -} - -impl Default for Error { - fn default() -> Self { - Self { - status: StatusCode::INTERNAL_SERVER_ERROR, - detail: None, - } - } -} - -impl Error { - pub fn with_status(status: StatusCode) -> Error { - Self { - status, - detail: None, - } - } - - /// Create a new [`Error`]. - pub fn new(status_code: StatusCode, message: Option) -> Error { - Self { - status: status_code, - detail: message.map(|m| m.to_string()), - } - } -} - -impl IntoResponse for Error { - fn into_response(self) -> axum::response::Response { - match self.detail { - Some(detail) => (self.status, detail).into_response(), - _ => (self.status,).into_response(), - } - } -} - -impl From for Error { - fn from(error: QueryRejection) -> Self { - Self::new(StatusCode::BAD_REQUEST, error.into()) - } -} - -impl From for Error { - fn from(error: ExtensionRejection) -> Self { - Self::new(StatusCode::BAD_REQUEST, error.into()) - } -} - -impl From for Error { - fn from(error: PathRejection) -> Self { - Self::new(StatusCode::BAD_REQUEST, error.into()) - } -} - -// === Pubky specific errors === - -impl From for Error { - fn from(error: pubky_common::auth::Error) -> Self { - Self::new(StatusCode::BAD_REQUEST, Some(error)) - } -} - -impl From for Error { - fn from(error: pkarr::Error) -> Self { - Self::new(StatusCode::BAD_REQUEST, Some(error)) - } -} - -// === INTERNAL_SERVER_ERROR === - -impl From for Error { - fn from(error: std::io::Error) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} - -impl From for Error { - fn from(error: heed::Error) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} - -impl From for Error { - fn from(error: anyhow::Error) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} - -impl From for Error { - fn from(error: postcard::Error) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} - -impl From for Error { - fn from(error: axum::Error) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} - -impl From> for Error { - fn from(error: flume::SendError) -> Self { - debug!(?error); - Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) - } -} diff --git a/rust/pubky/pubky-homeserver/src/extractors.rs b/rust/pubky/pubky-homeserver/src/extractors.rs deleted file mode 100644 index 779ce65..0000000 --- a/rust/pubky/pubky-homeserver/src/extractors.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::collections::HashMap; - -use axum::{ - async_trait, - extract::{FromRequestParts, Path, Query}, - http::{request::Parts, StatusCode}, - response::{IntoResponse, Response}, - RequestPartsExt, -}; - -use pkarr::PublicKey; - -use crate::error::{Error, Result}; - -#[derive(Debug)] -pub struct Pubky(PublicKey); - -impl Pubky { - pub fn public_key(&self) -> &PublicKey { - &self.0 - } -} - -#[async_trait] -impl FromRequestParts for Pubky -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { - let params: Path> = - parts.extract().await.map_err(IntoResponse::into_response)?; - - let pubky_id = params - .get("pubky") - .ok_or_else(|| (StatusCode::NOT_FOUND, "pubky param missing").into_response())?; - - let public_key = PublicKey::try_from(pubky_id.to_string()) - .map_err(Error::try_from) - .map_err(IntoResponse::into_response)?; - - // TODO: return 404 if the user doesn't exist, but exclude signups. - - Ok(Pubky(public_key)) - } -} - -pub struct EntryPath(pub(crate) String); - -impl EntryPath { - pub fn as_str(&self) -> &str { - self.0.as_str() - } -} - -#[async_trait] -impl FromRequestParts for EntryPath -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { - let params: Path> = - parts.extract().await.map_err(IntoResponse::into_response)?; - - // TODO: enforce path limits like no trailing '/' - - let path = params - .get("path") - .ok_or_else(|| (StatusCode::NOT_FOUND, "entry path missing").into_response())?; - - Ok(EntryPath(path.to_string())) - } -} - -#[derive(Debug)] -pub struct ListQueryParams { - pub limit: Option, - pub cursor: Option, - pub reverse: bool, - pub shallow: bool, -} - -#[async_trait] -impl FromRequestParts for ListQueryParams -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { - let params: Query> = - parts.extract().await.map_err(IntoResponse::into_response)?; - - let reverse = params.contains_key("reverse"); - let shallow = params.contains_key("shallow"); - let limit = params - .get("limit") - // Treat `limit=` as None - .and_then(|l| if l.is_empty() { None } else { Some(l) }) - .and_then(|l| l.parse::().ok()); - let cursor = params - .get("cursor") - .map(|c| c.as_str()) - // Treat `cursor=` as None - .and_then(|c| { - if c.is_empty() { - None - } else { - Some(c.to_string()) - } - }); - - Ok(ListQueryParams { - reverse, - shallow, - limit, - cursor, - }) - } -} diff --git a/rust/pubky/pubky-homeserver/src/lib.rs b/rust/pubky/pubky-homeserver/src/lib.rs deleted file mode 100644 index 4a1253b..0000000 --- a/rust/pubky/pubky-homeserver/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod config; -mod database; -mod error; -mod extractors; -mod pkarr; -mod routes; -mod server; - -pub use server::Homeserver; diff --git a/rust/pubky/pubky-homeserver/src/main.rs b/rust/pubky/pubky-homeserver/src/main.rs deleted file mode 100644 index dad25df..0000000 --- a/rust/pubky/pubky-homeserver/src/main.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::path::PathBuf; - -use anyhow::Result; -use pubky_homeserver::{config::Config, Homeserver}; - -use clap::Parser; - -#[derive(Parser, Debug)] -struct Cli { - /// [tracing_subscriber::EnvFilter] - #[clap(short, long)] - tracing_env_filter: Option, - - /// Run Homeserver in a local testnet - #[clap(long)] - testnet: bool, - - /// Optional Path to config file. - #[clap(short, long)] - config: Option, -} - -#[tokio::main] -async fn main() -> Result<()> { - let args = Cli::parse(); - - tracing_subscriber::fmt() - .with_env_filter( - args.tracing_env_filter - .unwrap_or("pubky_homeserver=debug,tower_http=debug".to_string()), - ) - .init(); - - let server = Homeserver::start(if args.testnet { - Config::testnet() - } else if let Some(config_path) = args.config { - Config::load(config_path).await? - } else { - Config::default() - }) - .await?; - - server.run_until_done().await?; - - Ok(()) -} diff --git a/rust/pubky/pubky-homeserver/src/pkarr.rs b/rust/pubky/pubky-homeserver/src/pkarr.rs deleted file mode 100644 index c23755e..0000000 --- a/rust/pubky/pubky-homeserver/src/pkarr.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! Pkarr related task - -use pkarr::{ - dns::{rdata::SVCB, Packet}, - Keypair, PkarrClientAsync, SignedPacket, -}; - -pub(crate) async fn publish_server_packet( - pkarr_client: &PkarrClientAsync, - keypair: &Keypair, - domain: &str, - port: u16, -) -> anyhow::Result<()> { - // TODO: Try to resolve first before publishing. - - let mut packet = Packet::new_reply(0); - - let mut svcb = SVCB::new(0, domain.try_into()?); - - // Publishing port only for localhost domain, - // assuming any other domain will point to a reverse proxy - // at the conventional ports. - if domain == "localhost" { - svcb.priority = 1; - svcb.set_port(port); - - // TODO: Add more parameteres like the signer key! - // svcb.set_param(key, value) - }; - - // TODO: announce A/AAAA records as well for Noise connections? - // Or maybe Iroh's magic socket - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "@".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), - )); - - let signed_packet = SignedPacket::from_packet(keypair, &packet)?; - - pkarr_client.publish(&signed_packet).await?; - - Ok(()) -} diff --git a/rust/pubky/pubky-homeserver/src/routes.rs b/rust/pubky/pubky-homeserver/src/routes.rs deleted file mode 100644 index 7422f20..0000000 --- a/rust/pubky/pubky-homeserver/src/routes.rs +++ /dev/null @@ -1,43 +0,0 @@ -use axum::{ - extract::DefaultBodyLimit, - routing::{delete, get, post, put}, - Router, -}; -use tower_cookies::CookieManagerLayer; -use tower_http::{cors::CorsLayer, trace::TraceLayer}; - -use crate::server::AppState; - -use self::pkarr::pkarr_router; - -mod auth; -mod feed; -mod pkarr; -mod public; -mod root; - -fn base(state: AppState) -> Router { - Router::new() - .route("/", get(root::handler)) - .route("/signup", post(auth::signup)) - .route("/session", post(auth::signin)) - .route("/:pubky/session", get(auth::session)) - .route("/:pubky/session", delete(auth::signout)) - .route("/:pubky/*path", put(public::put)) - .route("/:pubky/*path", get(public::get)) - .route("/:pubky/*path", delete(public::delete)) - .route("/events/", get(feed::feed)) - .layer(CookieManagerLayer::new()) - // TODO: revisit if we enable streaming big payloads - // TODO: maybe add to a separate router (drive router?). - .layer(DefaultBodyLimit::max(16 * 1024)) - .with_state(state) -} - -pub fn create_app(state: AppState) -> Router { - base(state.clone()) - // TODO: Only enable this for test environments? - .nest("/pkarr", pkarr_router(state)) - .layer(CorsLayer::very_permissive()) - .layer(TraceLayer::new_for_http()) -} diff --git a/rust/pubky/pubky-homeserver/src/routes/auth.rs b/rust/pubky/pubky-homeserver/src/routes/auth.rs deleted file mode 100644 index dbcffe4..0000000 --- a/rust/pubky/pubky-homeserver/src/routes/auth.rs +++ /dev/null @@ -1,138 +0,0 @@ -use axum::{ - debug_handler, - extract::State, - http::{uri::Scheme, StatusCode, Uri}, - response::IntoResponse, -}; -use axum_extra::{headers::UserAgent, TypedHeader}; -use bytes::Bytes; -use tower_cookies::{cookie::SameSite, Cookie, Cookies}; - -use pubky_common::{crypto::random_bytes, session::Session, timestamp::Timestamp}; - -use crate::{ - database::tables::{ - sessions::{SessionsTable, SESSIONS_TABLE}, - users::User, - }, - error::{Error, Result}, - extractors::Pubky, - server::AppState, -}; - -#[debug_handler] -pub async fn signup( - State(state): State, - user_agent: Option>, - cookies: Cookies, - uri: Uri, - body: Bytes, -) -> Result { - // TODO: Verify invitation link. - // TODO: add errors in case of already axisting user. - signin(State(state), user_agent, cookies, uri, body).await -} - -pub async fn session( - State(state): State, - cookies: Cookies, - pubky: Pubky, -) -> Result { - if let Some(cookie) = cookies.get(&pubky.public_key().to_string()) { - let rtxn = state.db.env.read_txn()?; - - let sessions: SessionsTable = state - .db - .env - .open_database(&rtxn, Some(SESSIONS_TABLE))? - .expect("Session table already created"); - - if let Some(session) = sessions.get(&rtxn, cookie.value())? { - let session = session.to_owned(); - rtxn.commit()?; - - // TODO: add content-type - return Ok(session); - }; - - rtxn.commit()?; - }; - - Err(Error::with_status(StatusCode::NOT_FOUND)) -} - -pub async fn signout( - State(state): State, - cookies: Cookies, - pubky: Pubky, -) -> Result { - if let Some(cookie) = cookies.get(&pubky.public_key().to_string()) { - let mut wtxn = state.db.env.write_txn()?; - - let sessions: SessionsTable = state - .db - .env - .open_database(&wtxn, Some(SESSIONS_TABLE))? - .expect("Session table already created"); - - let _ = sessions.delete(&mut wtxn, cookie.value()); - - wtxn.commit()?; - - return Ok(()); - }; - - Err(Error::with_status(StatusCode::UNAUTHORIZED)) -} - -pub async fn signin( - State(state): State, - user_agent: Option>, - cookies: Cookies, - uri: Uri, - body: Bytes, -) -> Result { - let token = state.verifier.verify(&body)?; - - let public_key = token.pubky(); - - let mut wtxn = state.db.env.write_txn()?; - - let users = state.db.tables.users; - if let Some(existing) = users.get(&wtxn, public_key)? { - users.put(&mut wtxn, public_key, &existing)?; - } else { - users.put( - &mut wtxn, - public_key, - &User { - created_at: Timestamp::now().into_inner(), - }, - )?; - } - - let session_secret = base32::encode(base32::Alphabet::Crockford, &random_bytes::<16>()); - - let session = Session::new(&token, user_agent.map(|ua| ua.to_string())).serialize(); - - state - .db - .tables - .sessions - .put(&mut wtxn, &session_secret, &session)?; - - let mut cookie = Cookie::new(public_key.to_string(), session_secret); - - cookie.set_path("/"); - if *uri.scheme().unwrap_or(&Scheme::HTTP) == Scheme::HTTPS { - cookie.set_secure(true); - cookie.set_same_site(SameSite::None); - } - cookie.set_http_only(true); - - cookies.add(cookie); - - wtxn.commit()?; - - Ok(session) -} diff --git a/rust/pubky/pubky-homeserver/src/routes/feed.rs b/rust/pubky/pubky-homeserver/src/routes/feed.rs deleted file mode 100644 index 6271aeb..0000000 --- a/rust/pubky/pubky-homeserver/src/routes/feed.rs +++ /dev/null @@ -1,41 +0,0 @@ -use axum::{ - body::Body, - extract::State, - http::{header, Response, StatusCode}, - response::IntoResponse, -}; -use pubky_common::timestamp::{Timestamp, TimestampError}; - -use crate::{ - error::{Error, Result}, - extractors::ListQueryParams, - server::AppState, -}; - -pub async fn feed( - State(state): State, - params: ListQueryParams, -) -> Result { - if let Some(ref cursor) = params.cursor { - if let Err(timestmap_error) = Timestamp::try_from(cursor.to_string()) { - let cause = match timestmap_error { - TimestampError::InvalidEncoding => { - "Cursor should be valid base32 Crockford encoding of a timestamp" - } - TimestampError::InvalidBytesLength(size) => { - &format!("Cursor should be 13 characters long, got: {size}") - } - }; - - Err(Error::new(StatusCode::BAD_REQUEST, cause.into()))? - } - } - - let result = state.db.list_events(params.limit, params.cursor)?; - - Ok(Response::builder() - .status(StatusCode::OK) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(result.join("\n"))) - .unwrap()) -} diff --git a/rust/pubky/pubky-homeserver/src/routes/pkarr.rs b/rust/pubky/pubky-homeserver/src/routes/pkarr.rs deleted file mode 100644 index 9e40230..0000000 --- a/rust/pubky/pubky-homeserver/src/routes/pkarr.rs +++ /dev/null @@ -1,58 +0,0 @@ -use axum::{ - body::{Body, Bytes}, - extract::State, - http::StatusCode, - response::IntoResponse, - routing::{get, put}, - Router, -}; -use futures_util::stream::StreamExt; - -use pkarr::SignedPacket; - -use crate::{ - error::{Error, Result}, - extractors::Pubky, - server::AppState, -}; - -/// Pkarr relay, helpful for testing. -/// -/// For real productioin, you should use a [production ready -/// relay](https://github.com/pubky/pkarr/server). -pub fn pkarr_router(state: AppState) -> Router { - Router::new() - .route("/:pubky", put(pkarr_put)) - .route("/:pubky", get(pkarr_get)) - .with_state(state) -} - -pub async fn pkarr_put( - State(state): State, - pubky: Pubky, - body: Body, -) -> Result { - let mut bytes = Vec::with_capacity(1104); - - let mut stream = body.into_data_stream(); - - while let Some(chunk) = stream.next().await { - bytes.extend_from_slice(&chunk?) - } - - let public_key = pubky.public_key().to_owned(); - - let signed_packet = SignedPacket::from_relay_payload(&public_key, &Bytes::from(bytes))?; - - state.pkarr_client.publish(&signed_packet).await?; - - Ok(()) -} - -pub async fn pkarr_get(State(state): State, pubky: Pubky) -> Result { - if let Some(signed_packet) = state.pkarr_client.resolve(pubky.public_key()).await? { - return Ok(signed_packet.to_relay_payload()); - } - - Err(Error::with_status(StatusCode::NOT_FOUND)) -} diff --git a/rust/pubky/pubky-homeserver/src/routes/public.rs b/rust/pubky/pubky-homeserver/src/routes/public.rs deleted file mode 100644 index 8c6b2b9..0000000 --- a/rust/pubky/pubky-homeserver/src/routes/public.rs +++ /dev/null @@ -1,174 +0,0 @@ -use axum::{ - body::{Body, Bytes}, - extract::State, - http::{header, Response, StatusCode}, - response::IntoResponse, -}; -use futures_util::stream::StreamExt; -use pkarr::PublicKey; -use tower_cookies::Cookies; - -use crate::{ - error::{Error, Result}, - extractors::{EntryPath, ListQueryParams, Pubky}, - server::AppState, -}; - -pub async fn put( - State(mut state): State, - pubky: Pubky, - path: EntryPath, - cookies: Cookies, - body: Body, -) -> Result { - let public_key = pubky.public_key().clone(); - let path = path.as_str(); - - verify(path)?; - authorize(&mut state, cookies, &public_key, path)?; - - let mut stream = body.into_data_stream(); - - let (tx, rx) = flume::bounded::(1); - - let path = path.to_string(); - - // TODO: refactor Database to clean up this scope. - let done = tokio::task::spawn_blocking(move || -> Result<()> { - // TODO: this is a blocking operation, which is ok for small - // payloads (we have 16 kb limit for now) but later we need - // to stream this to filesystem, and keep track of any failed - // writes to GC these files later. - - state.db.put_entry(&public_key, &path, rx)?; - - Ok(()) - }); - - while let Some(next) = stream.next().await { - let chunk = next?; - - tx.send(chunk)?; - } - - drop(tx); - done.await.expect("join error")?; - - // TODO: return relevant headers, like Etag? - - Ok(()) -} - -pub async fn get( - State(state): State, - pubky: Pubky, - path: EntryPath, - params: ListQueryParams, -) -> Result { - verify(path.as_str())?; - let public_key = pubky.public_key(); - - let path = path.as_str(); - - if path.ends_with('/') { - let txn = state.db.env.read_txn()?; - - let path = format!("{public_key}/{path}"); - - if !state.db.contains_directory(&txn, &path)? { - return Err(Error::new( - StatusCode::NOT_FOUND, - "Directory Not Found".into(), - )); - } - - // Handle listing - let vec = state.db.list( - &txn, - &path, - params.reverse, - params.limit, - params.cursor, - params.shallow, - )?; - - return Ok(Response::builder() - .status(StatusCode::OK) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(vec.join("\n"))) - .unwrap()); - } - - // TODO: Enable streaming - - match state.db.get_blob(public_key, path) { - Err(error) => Err(error)?, - Ok(Some(bytes)) => Ok(Response::builder().body(Body::from(bytes)).unwrap()), - Ok(None) => Err(Error::new(StatusCode::NOT_FOUND, "File Not Found".into())), - } -} - -pub async fn delete( - State(mut state): State, - pubky: Pubky, - path: EntryPath, - cookies: Cookies, -) -> Result { - let public_key = pubky.public_key().clone(); - let path = path.as_str(); - - authorize(&mut state, cookies, &public_key, path)?; - verify(path)?; - - let deleted = state.db.delete_entry(&public_key, path)?; - - if !deleted { - // TODO: if the path ends with `/` return a `CONFLICT` error? - return Err(Error::with_status(StatusCode::NOT_FOUND)); - } - - // TODO: return relevant headers, like Etag? - - Ok(()) -} - -/// Authorize write (PUT or DELETE) for Public paths. -fn authorize( - state: &mut AppState, - cookies: Cookies, - public_key: &PublicKey, - path: &str, -) -> Result<()> { - // TODO: can we move this logic to the extractor or a layer - // to perform this validation? - let session = state - .db - .get_session(cookies, public_key)? - .ok_or(Error::with_status(StatusCode::UNAUTHORIZED))?; - - if session.pubky() == public_key - && session.capabilities().iter().any(|cap| { - path.starts_with(&cap.scope[1..]) - && cap - .actions - .contains(&pubky_common::capabilities::Action::Write) - }) - { - return Ok(()); - } - - Err(Error::with_status(StatusCode::FORBIDDEN)) -} - -fn verify(path: &str) -> Result<()> { - if !path.starts_with("pub/") { - return Err(Error::new( - StatusCode::FORBIDDEN, - "Writing to directories other than '/pub/' is forbidden".into(), - )); - } - - // TODO: should we forbid paths ending with `/`? - - Ok(()) -} diff --git a/rust/pubky/pubky-homeserver/src/routes/root.rs b/rust/pubky/pubky-homeserver/src/routes/root.rs deleted file mode 100644 index 35a9482..0000000 --- a/rust/pubky/pubky-homeserver/src/routes/root.rs +++ /dev/null @@ -1,5 +0,0 @@ -use axum::response::IntoResponse; - -pub async fn handler() -> Result { - Ok("This a Pubky homeserver.".to_string()) -} diff --git a/rust/pubky/pubky-homeserver/src/server.rs b/rust/pubky/pubky-homeserver/src/server.rs deleted file mode 100644 index d44d346..0000000 --- a/rust/pubky/pubky-homeserver/src/server.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::{future::IntoFuture, net::SocketAddr}; - -use anyhow::{Error, Result}; -use pubky_common::auth::AuthVerifier; -use tokio::{net::TcpListener, signal, task::JoinSet}; -use tracing::{debug, info, warn}; - -use pkarr::{ - mainline::dht::{DhtSettings, Testnet}, - PkarrClient, PkarrClientAsync, PublicKey, Settings, -}; - -use crate::{config::Config, database::DB, pkarr::publish_server_packet}; - -#[derive(Debug)] -pub struct Homeserver { - state: AppState, - tasks: JoinSet>, -} - -#[derive(Clone, Debug)] -pub(crate) struct AppState { - pub(crate) verifier: AuthVerifier, - pub(crate) db: DB, - pub(crate) pkarr_client: PkarrClientAsync, - pub(crate) config: Config, - pub(crate) port: u16, -} - -impl Homeserver { - pub async fn start(config: Config) -> Result { - debug!(?config); - - let db = DB::open(config.clone())?; - - let pkarr_client = PkarrClient::new(Settings { - dht: DhtSettings { - bootstrap: config.bootstsrap(), - request_timeout: config.dht_request_timeout(), - ..Default::default() - }, - ..Default::default() - })? - .as_async(); - - let mut tasks = JoinSet::new(); - - let listener = TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], config.port()))).await?; - - let port = listener.local_addr()?.port(); - - let state = AppState { - verifier: AuthVerifier::default(), - db, - pkarr_client, - config: config.clone(), - port, - }; - - let app = crate::routes::create_app(state.clone()); - - // Spawn http server task - tasks.spawn( - axum::serve( - listener, - app.into_make_service_with_connect_info::(), - ) - .with_graceful_shutdown(shutdown_signal()) - .into_future(), - ); - - info!("Homeserver listening on http://localhost:{port}"); - - publish_server_packet( - &state.pkarr_client, - config.keypair(), - &state - .config - .domain() - .clone() - .unwrap_or("localhost".to_string()), - port, - ) - .await?; - - info!( - "Homeserver listening on pubky://{}", - config.keypair().public_key() - ); - - Ok(Self { tasks, state }) - } - - /// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage. - pub async fn start_test(testnet: &Testnet) -> Result { - info!("Running testnet.."); - - Homeserver::start(Config::test(testnet)).await - } - - // === Getters === - - pub fn port(&self) -> u16 { - self.state.port - } - - pub fn public_key(&self) -> PublicKey { - self.state.config.keypair().public_key() - } - - // === Public Methods === - - /// Shutdown the server and wait for all tasks to complete. - pub async fn shutdown(mut self) -> Result<()> { - self.tasks.abort_all(); - self.run_until_done().await?; - Ok(()) - } - - /// Wait for all tasks to complete. - /// - /// Runs forever unless tasks fail. - pub async fn run_until_done(mut self) -> Result<()> { - let mut final_res: Result<()> = Ok(()); - while let Some(res) = self.tasks.join_next().await { - match res { - Ok(Ok(())) => {} - Err(err) if err.is_cancelled() => {} - Ok(Err(err)) => { - warn!(?err, "task failed"); - final_res = Err(Error::from(err)); - } - Err(err) => { - warn!(?err, "task panicked"); - final_res = Err(err.into()); - } - } - } - final_res - } -} - -async fn shutdown_signal() { - let ctrl_c = async { - signal::ctrl_c() - .await - .expect("failed to install Ctrl+C handler"); - }; - - #[cfg(unix)] - let terminate = async { - signal::unix::signal(signal::unix::SignalKind::terminate()) - .expect("failed to install signal handler") - .recv() - .await; - }; - - #[cfg(not(unix))] - let terminate = std::future::pending::<()>(); - - fn graceful_shutdown() { - info!("Gracefully Shutting down.."); - } - - tokio::select! { - _ = ctrl_c => graceful_shutdown(), - _ = terminate => graceful_shutdown(), - } -} diff --git a/rust/pubky/pubky/Cargo.toml b/rust/pubky/pubky/Cargo.toml deleted file mode 100644 index 6871377..0000000 --- a/rust/pubky/pubky/Cargo.toml +++ /dev/null @@ -1,44 +0,0 @@ -[package] -name = "pubky" -version = "0.1.0" -edition = "2021" -description = "Pubky client" -license = "MIT" -repository = "https://github.com/pubky/pubky" -keywords = ["web", "dht", "dns", "decentralized", "identity"] - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -thiserror = "1.0.62" -wasm-bindgen = "0.2.92" -url = "2.5.2" -bytes = "^1.7.1" -base64 = "0.22.1" - -pubky-common = { version = "0.1.0", path = "../pubky-common" } -pkarr = { workspace = true, features = ["async"] } - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -reqwest = { version = "0.12.5", features = ["cookies", "rustls-tls"], default-features = false } -tokio = { version = "1.37.0", features = ["full"] } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -reqwest = { version = "0.12.5", default-features = false } - -js-sys = "0.3.69" -wasm-bindgen = "0.2.92" -wasm-bindgen-futures = "0.4.42" - -[dev-dependencies] -pubky_homeserver = { path = "../pubky-homeserver" } -tokio = "1.37.0" - -[features] - -[package.metadata.docs.rs] -all-features = true - -[package.metadata.wasm-pack.profile.release] -wasm-opt = ['-g', '-O'] diff --git a/rust/pubky/pubky/pkg/.gitignore b/rust/pubky/pubky/pkg/.gitignore deleted file mode 100644 index 7355b75..0000000 --- a/rust/pubky/pubky/pkg/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -index.cjs -browser.js -coverage -node_modules -package-lock.json -pubky* diff --git a/rust/pubky/pubky/pkg/LICENSE b/rust/pubky/pubky/pkg/LICENSE deleted file mode 100644 index a0e67c5..0000000 --- a/rust/pubky/pubky/pkg/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2023 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/rust/pubky/pubky/pkg/README.md b/rust/pubky/pubky/pkg/README.md deleted file mode 100644 index 81b2cf4..0000000 --- a/rust/pubky/pubky/pkg/README.md +++ /dev/null @@ -1,266 +0,0 @@ -# Pubky - -JavaScript implementation of [Pubky](https://github.com/pubky/pubky). - -## Table of Contents -- [Install](#install) -- [Getting Started](#getting-started) -- [API](#api) -- [Test and Development](#test-and-development) - -## Install - -```bash -npm install @synonymdev/pubky -``` - -### Prerequisites - -For Nodejs, you need Node v20 or later. - -## Getting started - -```js -import { PubkyClient, Keypair, PublicKey } from '../index.js' - -// Initialize PubkyClient with Pkarr relay(s). -let client = new PubkyClient(); - -// Generate a keypair -let keypair = Keypair.random(); - -// Create a new account -let homeserver = PublicKey.from("8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"); - -await client.signup(keypair, homeserver) - -const publicKey = keypair.publicKey(); - -// Pubky URL -let url = `pubky://${publicKey.z32()}/pub/example.com/arbitrary`; - -// Verify that you are signed in. -const session = await client.session(publicKey) - -const body = Buffer.from(JSON.stringify({ foo: 'bar' })) - -// PUT public data, by authorized client -await client.put(url, body); - -// GET public data without signup or signin -{ - const client = new PubkyClient(); - - let response = await client.get(url); -} - -// Delete public data, by authorized client -await client.delete(url); -``` - -## API - -### PubkyClient - -#### constructor -```js -let client = new PubkyClient() -``` - -#### signup -```js -await client.signup(keypair, homeserver) -``` -- keypair: An instance of [Keypair](#keypair). -- homeserver: An instance of [PublicKey](#publickey) representing the homeserver. - -Returns: -- session: An instance of [Session](#session). - -#### signin -```js -let session = await client.signin(keypair) -``` -- keypair: An instance of [Keypair](#keypair). - -Returns: -- An instance of [Session](#session). - -#### signout -```js -await client.signout(publicKey) -``` -- publicKey: An instance of [PublicKey](#publicKey). - -#### authRequest -```js -let [pubkyauthUrl, sessionPromise] = client.authRequest(relay, capabilities); - -showQr(pubkyauthUrl); - -let pubky = await sessionPromise; -``` - -Sign in to a user's Homeserver, without access to their [Keypair](#keypair), nor even [PublicKey](#publickey), -instead request permissions (showing the user pubkyauthUrl), and await a Session after the user consenting to that request. - -- relay: A URL to an [HTTP relay](https://httprelay.io/features/link/) endpoint. -- capabilities: A list of capabilities required for the app for example `/pub/pubky.app/:rw,/pub/example.com/:r`. - -Returns: -- pubkyauthUrl: A url to show to the user to scan or paste into an Authenticator app holding the user [Keypair](#keypair) -- sessionPromise: A promise that resolves into a [PublicKey](#publickey) on success, which you can use in `client.session(pubky)` to resolve more information about the Session. - -#### sendAuthToken -```js -await client.sendAuthToken(keypair, pubkyauthUrl); -``` -Consenting to authentication or authorization according to the required capabilities in the `pubkyauthUrl` , and sign and send an auth token to the requester. - -- keypair: An instance of [KeyPair](#keypair) -- pubkyauthUrl: A string `pubkyauth://` url - -#### session {#session-method} -```js -let session = await client.session(publicKey) -``` -- publicKey: An instance of [PublicKey](#publickey). -- Returns: A [Session](#session) object if signed in, or undefined if not. - -#### put -```js -let response = await client.put(url, body); -``` -- url: A string representing the Pubky URL. -- body: A Buffer containing the data to be stored. - -### get -```js -let response = await client.get(url) -``` -- url: A string representing the Pubky URL. -- Returns: A Uint8Array object containing the requested data, or `undefined` if `NOT_FOUND`. - -### delete - -```js -let response = await client.delete(url); -``` -- url: A string representing the Pubky URL. - -### list -```js -let response = await client.list(url, cursor, reverse, limit) -``` -- url: A string representing the Pubky URL. The path in that url is the prefix that you want to list files within. -- cursor: Usually the last URL from previous calls. List urls after/before (depending on `reverse`) the cursor. -- reverse: Whether or not return urls in reverse order. -- limit: Number of urls to return. -- Returns: A list of URLs of the files in the `url` you passed. - -### Keypair - -#### random -```js -let keypair = Keypair.random() -``` -- Returns: A new random Keypair. - -#### fromSecretKey -```js -let keypair = Keypair.fromSecretKey(secretKey) -``` -- secretKey: A 32 bytes Uint8array. -- Returns: A new Keypair. - - -#### publicKey {#publickey-method} -```js -let publicKey = keypair.publicKey() -``` -- Returns: The [PublicKey](#publickey) associated with the Keypair. - -#### secretKey -```js -let secretKey = keypair.secretKey() -``` -- Returns: The Uint8array secret key associated with the Keypair. - -### PublicKey - -#### from - -```js -let publicKey = PublicKey.from(string); -``` -- string: A string representing the public key. -- Returns: A new PublicKey instance. - -#### z32 -```js -let pubky = publicKey.z32(); -``` -Returns: The z-base-32 encoded string representation of the PublicKey. - -### Session - -#### pubky -```js -let pubky = session.pubky(); -``` -Returns an instance of [PublicKey](#publickey) - -#### capabilities -```js -let capabilities = session.capabilities(); -``` -Returns an array of capabilities, for example `["/pub/pubky.app/:rw"]` - -### Helper functions - -#### createRecoveryFile -```js -let recoveryFile = createRecoveryFile(keypair, passphrase) -``` -- keypair: An instance of [Keypair](#keypair). -- passphrase: A utf-8 string [passphrase](https://www.useapassphrase.com/). -- Returns: A recovery file with a spec line and an encrypted secret key. - -#### createRecoveryFile -```js -let keypair = decryptRecoveryfile(recoveryFile, passphrase) -``` -- recoveryFile: An instance of Uint8Array containing the recovery file blob. -- passphrase: A utf-8 string [passphrase](https://www.useapassphrase.com/). -- Returns: An instance of [Keypair](#keypair). - -## Test and Development - -For test and development, you can run a local homeserver in a test network. - -If you don't have Cargo Installed, start by installing it: - -```bash -curl https://sh.rustup.rs -sSf | sh -``` - -Clone the Pubky repository: - -```bash -git clone https://github.com/pubky/pubky -cd pubky/pkg -``` - -Run the local testnet server - -```bash -npm run testnet -``` - -Use the logged addresses as inputs to `PubkyClient` - -```js -import { PubkyClient } from '../index.js' - -const client = PubkyClient().testnet(); -``` diff --git a/rust/pubky/pubky/pkg/package.json b/rust/pubky/pubky/pkg/package.json deleted file mode 100644 index be3e6df..0000000 --- a/rust/pubky/pubky/pkg/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "@synonymdev/pubky", - "type": "module", - "description": "Pubky client", - "version": "0.1.16", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/pubky/pubky" - }, - "scripts": { - "testnet": "cargo run -p pubky_homeserver -- --testnet", - "test": "npm run test-nodejs && npm run test-browser", - "test-nodejs": "tape test/*.js -cov", - "test-browser": "browserify test/*.js -p esmify | npx tape-run", - "build": "cargo run --bin bundle_pubky_npm", - "prepublishOnly": "npm run build && npm run test" - }, - "files": [ - "index.cjs", - "browser.js", - "pubky.d.ts", - "pubky_bg.wasm" - ], - "main": "index.cjs", - "browser": "browser.js", - "types": "pubky.d.ts", - "keywords": [ - "web", - "dht", - "dns", - "decentralized", - "identity" - ], - "devDependencies": { - "browser-resolve": "^2.0.0", - "esmify": "^2.1.1", - "tape": "^5.8.1", - "tape-run": "^11.0.0" - } -} diff --git a/rust/pubky/pubky/pkg/test/auth.js b/rust/pubky/pubky/pkg/test/auth.js deleted file mode 100644 index fe7e559..0000000 --- a/rust/pubky/pubky/pkg/test/auth.js +++ /dev/null @@ -1,65 +0,0 @@ -import test from 'tape' - -import { PubkyClient, Keypair, PublicKey } from '../index.cjs' - -const Homeserver = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo') - -test('auth', async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random() - const publicKey = keypair.publicKey() - - await client.signup(keypair, Homeserver) - - const session = await client.session(publicKey) - t.ok(session, "signup") - - { - await client.signout(publicKey) - - const session = await client.session(publicKey) - t.notOk(session, "singout") - } - - { - await client.signin(keypair) - - const session = await client.session(publicKey) - t.ok(session, "signin") - } -}) - -test("3rd party signin", async (t) => { - let keypair = Keypair.random(); - let pubky = keypair.publicKey().z32(); - - // Third party app side - let capabilities = "/pub/pubky.app/:rw,/pub/foo.bar/file:r"; - let client = PubkyClient.testnet(); - let [pubkyauth_url, pubkyauthResponse] = client - .authRequest("https://demo.httprelay.io/link", capabilities); - - if (globalThis.document) { - // Skip `sendAuthToken` in browser - // TODO: figure out why does it fail in browser unit tests - // but not in real browser (check pubky-auth-widget.js commented part) - return - } - - // Authenticator side - { - let client = PubkyClient.testnet(); - - await client.signup(keypair, Homeserver); - - await client.sendAuthToken(keypair, pubkyauth_url) - } - - let authedPubky = await pubkyauthResponse; - - t.is(authedPubky.z32(), pubky); - - let session = await client.session(authedPubky); - t.deepEqual(session.capabilities(), capabilities.split(',')) -}) diff --git a/rust/pubky/pubky/pkg/test/keys.js b/rust/pubky/pubky/pkg/test/keys.js deleted file mode 100644 index d036862..0000000 --- a/rust/pubky/pubky/pkg/test/keys.js +++ /dev/null @@ -1,21 +0,0 @@ -import test from 'tape' - -import { Keypair } from '../index.cjs' - -test('generate keys from a seed', async (t) => { - const secretkey = Buffer.from('5aa93b299a343aa2691739771f2b5b85e740ca14c685793d67870f88fa89dc51', 'hex') - - const keypair = Keypair.fromSecretKey(secretkey) - - const publicKey = keypair.publicKey() - - t.is(publicKey.z32(), 'gcumbhd7sqit6nn457jxmrwqx9pyymqwamnarekgo3xppqo6a19o') -}) - -test('fromSecretKey error', async (t) => { - const secretkey = Buffer.from('5aa93b299a343aa2691739771f2b5b', 'hex') - - - t.throws(() => Keypair.fromSecretKey(null), /Expected secret_key to be an instance of Uint8Array/) - t.throws(() => Keypair.fromSecretKey(secretkey), /Expected secret_key to be 32 bytes, got 15/) -}) diff --git a/rust/pubky/pubky/pkg/test/public.js b/rust/pubky/pubky/pkg/test/public.js deleted file mode 100644 index ec30bb2..0000000 --- a/rust/pubky/pubky/pkg/test/public.js +++ /dev/null @@ -1,351 +0,0 @@ -import test from 'tape' - -import { PubkyClient, Keypair, PublicKey } from '../index.cjs' - -const Homeserver = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo'); - -test('public: put/get', async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random(); - - await client.signup(keypair, Homeserver); - - const publicKey = keypair.publicKey(); - - let url = `pubky://${publicKey.z32()}/pub/example.com/arbitrary`; - - const body = Buffer.from(JSON.stringify({ foo: 'bar' })) - - // PUT public data, by authorized client - await client.put(url, body); - - const otherClient = PubkyClient.testnet(); - - // GET public data without signup or signin - { - let response = await otherClient.get(url); - - t.ok(Buffer.from(response).equals(body)) - } - - // DELETE public data, by authorized client - await client.delete(url); - - - // GET public data without signup or signin - { - let response = await otherClient.get(url); - - t.notOk(response) - } -}) - -test("not found", async (t) => { - const client = PubkyClient.testnet(); - - - const keypair = Keypair.random(); - - await client.signup(keypair, Homeserver); - - const publicKey = keypair.publicKey(); - - let url = `pubky://${publicKey.z32()}/pub/example.com/arbitrary`; - - let result = await client.get(url).catch(e => e); - - t.notOk(result); -}) - -test("unauthorized", async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random() - const publicKey = keypair.publicKey() - - await client.signup(keypair, Homeserver) - - const session = await client.session(publicKey) - t.ok(session, "signup") - - await client.signout(publicKey) - - const body = Buffer.from(JSON.stringify({ foo: 'bar' })) - - let url = `pubky://${publicKey.z32()}/pub/example.com/arbitrary`; - - // PUT public data, by authorized client - let result = await client.put(url, body).catch(e => e); - - t.ok(result instanceof Error); - t.is( - result.message, - `HTTP status client error (401 Unauthorized) for url (http://localhost:15411/${publicKey.z32()}/pub/example.com/arbitrary)` - ) -}) - -test("forbidden", async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random() - const publicKey = keypair.publicKey() - - await client.signup(keypair, Homeserver) - - const session = await client.session(publicKey) - t.ok(session, "signup") - - const body = Buffer.from(JSON.stringify({ foo: 'bar' })) - - let url = `pubky://${publicKey.z32()}/priv/example.com/arbitrary`; - - // PUT public data, by authorized client - let result = await client.put(url, body).catch(e => e); - - t.ok(result instanceof Error); - t.is( - result.message, - `HTTP status client error (403 Forbidden) for url (http://localhost:15411/${publicKey.z32()}/priv/example.com/arbitrary)` - ) -}) - -test("list", async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random() - const publicKey = keypair.publicKey() - const pubky = publicKey.z32() - - await client.signup(keypair, Homeserver) - - - - let urls = [ - `pubky://${pubky}/pub/a.wrong/a.txt`, - `pubky://${pubky}/pub/example.com/a.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.wrong/a.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - `pubky://${pubky}/pub/example.com/d.txt`, - `pubky://${pubky}/pub/z.wrong/a.txt`, - ] - - for (let url of urls) { - await client.put(url, Buffer.from("")); - } - - let url = `pubky://${pubky}/pub/example.com/`; - - { - let list = await client.list(url); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/a.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - `pubky://${pubky}/pub/example.com/d.txt`, - - ], - "normal list with no limit or cursor" - ); - } - - { - let list = await client.list(url, null, null, 2); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/a.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - - ], - "normal list with limit but no cursor" - ); - } - - { - let list = await client.list(url, "a.txt", null, 2); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - - ], - "normal list with limit and a suffix cursor" - ); - } - - { - let list = await client.list(url, `pubky://${pubky}/pub/example.com/a.txt`, null, 2); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - - ], - "normal list with limit and a full url cursor" - ); - } - - - { - let list = await client.list(url, null, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/d.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.com/a.txt`, - - ], - "reverse list with no limit or cursor" - ); - } - - { - let list = await client.list(url, null, true, 2); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/d.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - - ], - "reverse list with limit but no cursor" - ); - } - - { - let list = await client.list(url, "d.txt", true, 2); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.com/c.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - - ], - "reverse list with limit and a suffix cursor" - ); - } -}) - -test('list shallow', async (t) => { - const client = PubkyClient.testnet(); - - const keypair = Keypair.random() - const publicKey = keypair.publicKey() - const pubky = publicKey.z32() - - await client.signup(keypair, Homeserver) - - let urls = [ - `pubky://${pubky}/pub/a.com/a.txt`, - `pubky://${pubky}/pub/example.com/a.txt`, - `pubky://${pubky}/pub/example.com/b.txt`, - `pubky://${pubky}/pub/example.com/c.txt`, - `pubky://${pubky}/pub/example.com/d.txt`, - `pubky://${pubky}/pub/example.con/d.txt`, - `pubky://${pubky}/pub/example.con`, - `pubky://${pubky}/pub/file`, - `pubky://${pubky}/pub/file2`, - `pubky://${pubky}/pub/z.com/a.txt`, - ] - - for (let url of urls) { - await client.put(url, Buffer.from("")); - } - - let url = `pubky://${pubky}/pub/`; - - { - let list = await client.list(url, null, false, null, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/a.com/`, - `pubky://${pubky}/pub/example.com/`, - `pubky://${pubky}/pub/example.con`, - `pubky://${pubky}/pub/example.con/`, - `pubky://${pubky}/pub/file`, - `pubky://${pubky}/pub/file2`, - `pubky://${pubky}/pub/z.com/`, - ], - "normal list shallow" - ); - } - - { - let list = await client.list(url, null, false, 3, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/a.com/`, - `pubky://${pubky}/pub/example.com/`, - `pubky://${pubky}/pub/example.con`, - ], - "normal list shallow with limit" - ); - } - - { - let list = await client.list(url, `example.com/`, false, null, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/example.con`, - `pubky://${pubky}/pub/example.con/`, - `pubky://${pubky}/pub/file`, - `pubky://${pubky}/pub/file2`, - `pubky://${pubky}/pub/z.com/`, - ], - "normal list shallow with cursor" - ); - } - - { - let list = await client.list(url, null, true, null, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/z.com/`, - `pubky://${pubky}/pub/file2`, - `pubky://${pubky}/pub/file`, - `pubky://${pubky}/pub/example.con/`, - `pubky://${pubky}/pub/example.con`, - `pubky://${pubky}/pub/example.com/`, - `pubky://${pubky}/pub/a.com/`, - ], - "normal list shallow" - ); - } - - { - let list = await client.list(url, null, true, 3, true); - - t.deepEqual( - list, - [ - `pubky://${pubky}/pub/z.com/`, - `pubky://${pubky}/pub/file2`, - `pubky://${pubky}/pub/file`, - ], - "normal list shallow with limit" - ); - } -}) diff --git a/rust/pubky/pubky/pkg/test/recovery.js b/rust/pubky/pubky/pkg/test/recovery.js deleted file mode 100644 index 0c033e5..0000000 --- a/rust/pubky/pubky/pkg/test/recovery.js +++ /dev/null @@ -1,19 +0,0 @@ -import test from 'tape' - -import { Keypair, createRecoveryFile, decryptRecoveryFile } from '../index.cjs' - -test('recovery', async (t) => { - const keypair = Keypair.random(); - - const recoveryFile = createRecoveryFile(keypair, 'very secure password'); - - t.is(recoveryFile.length, 91) - t.deepEqual( - Array.from(recoveryFile.slice(0, 19)), - [112, 117, 98, 107, 121, 46, 111, 114, 103, 47, 114, 101, 99, 111, 118, 101, 114, 121, 10] - ) - - const recovered = decryptRecoveryFile(recoveryFile, 'very secure password') - - t.is(recovered.publicKey().z32(), keypair.publicKey().z32()) -}) diff --git a/rust/pubky/pubky/src/bin/bundle_pubky_npm.rs b/rust/pubky/pubky/src/bin/bundle_pubky_npm.rs deleted file mode 100644 index 40e9b90..0000000 --- a/rust/pubky/pubky/src/bin/bundle_pubky_npm.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::env; -use std::io; -use std::process::{Command, ExitStatus}; - -// If the process hangs, try `cargo clean` to remove all locks. - -fn main() { - println!("Building wasm for pubky..."); - - build_wasm("nodejs").unwrap(); - patch().unwrap(); -} - -fn build_wasm(target: &str) -> io::Result { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); - - let output = Command::new("wasm-pack") - .args([ - "build", - &manifest_dir, - "--release", - "--target", - target, - "--out-dir", - &format!("pkg/{}", target), - ]) - .output()?; - - println!( - "wasm-pack {target} output: {}", - String::from_utf8_lossy(&output.stdout) - ); - - if !output.status.success() { - eprintln!( - "wasm-pack failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - Ok(output.status) -} - -fn patch() -> io::Result { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); - - println!("{manifest_dir}/src/bin/patch.mjs"); - let output = Command::new("node") - .args([format!("{manifest_dir}/src/bin/patch.mjs")]) - .output()?; - - println!( - "patch.mjs output: {}", - String::from_utf8_lossy(&output.stdout) - ); - - if !output.status.success() { - eprintln!( - "patch.mjs failed: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - - Ok(output.status) -} diff --git a/rust/pubky/pubky/src/bin/patch.mjs b/rust/pubky/pubky/src/bin/patch.mjs deleted file mode 100644 index a8ed503..0000000 --- a/rust/pubky/pubky/src/bin/patch.mjs +++ /dev/null @@ -1,66 +0,0 @@ -// This script is used to generate isomorphic code for web and nodejs -// -// Based on hacks from [this issue](https://github.com/rustwasm/wasm-pack/issues/1334) - -import { readFile, writeFile, rename } from "node:fs/promises"; -import { fileURLToPath } from 'node:url'; -import path, { dirname } from 'node:path'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const cargoTomlContent = await readFile(path.join(__dirname, "../../Cargo.toml"), "utf8"); -const cargoPackageName = /\[package\]\nname = "(.*?)"/.exec(cargoTomlContent)[1] -const name = cargoPackageName.replace(/-/g, '_') - -const content = await readFile(path.join(__dirname, `../../pkg/nodejs/${name}.js`), "utf8"); - -const patched = content - // use global TextDecoder TextEncoder - .replace("require(`util`)", "globalThis") - // attach to `imports` instead of module.exports - .replace("= module.exports", "= imports") - // Export classes - .replace(/\nclass (.*?) \{/g, "\n export class $1 {") - // Export functions - .replace(/\nmodule.exports.(.*?) = function/g, "\nimports.$1 = $1;\nexport function $1") - // Add exports to 'imports' - .replace(/\nmodule\.exports\.(.*?)\s+/g, "\nimports.$1") - // Export default - .replace(/$/, 'export default imports') - // inline wasm bytes - .replace( - /\nconst path.*\nconst bytes.*\n/, - ` -var __toBinary = /* @__PURE__ */ (() => { - var table = new Uint8Array(128); - for (var i = 0; i < 64; i++) - table[i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i * 4 - 205] = i; - return (base64) => { - var n = base64.length, bytes = new Uint8Array((n - (base64[n - 1] == "=") - (base64[n - 2] == "=")) * 3 / 4 | 0); - for (var i2 = 0, j = 0; i2 < n; ) { - var c0 = table[base64.charCodeAt(i2++)], c1 = table[base64.charCodeAt(i2++)]; - var c2 = table[base64.charCodeAt(i2++)], c3 = table[base64.charCodeAt(i2++)]; - bytes[j++] = c0 << 2 | c1 >> 4; - bytes[j++] = c1 << 4 | c2 >> 2; - bytes[j++] = c2 << 6 | c3; - } - return bytes; - }; -})(); - -const bytes = __toBinary(${JSON.stringify(await readFile(path.join(__dirname, `../../pkg/nodejs/${name}_bg.wasm`), "base64")) - }); -`, - ); - -await writeFile(path.join(__dirname, `../../pkg/browser.js`), patched + "\nglobalThis['pubky'] = imports"); - -// Move outside of nodejs - -await Promise.all([".js", ".d.ts", "_bg.wasm"].map(suffix => - rename( - path.join(__dirname, `../../pkg/nodejs/${name}${suffix}`), - path.join(__dirname, `../../pkg/${suffix === '.js' ? "index.cjs" : (name + suffix)}`), - )) -) diff --git a/rust/pubky/pubky/src/error.rs b/rust/pubky/pubky/src/error.rs deleted file mode 100644 index c8d80e1..0000000 --- a/rust/pubky/pubky/src/error.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! Main Crate Error - -use pkarr::dns::SimpleDnsError; - -// Alias Result to be the crate Result. -pub type Result = core::result::Result; - -#[derive(thiserror::Error, Debug)] -/// Pk common Error -pub enum Error { - /// For starter, to remove as code matures. - #[error("Generic error: {0}")] - Generic(String), - - #[error("Could not resolve endpoint for {0}")] - ResolveEndpoint(String), - - #[error("Could not convert the passed type into a Url")] - InvalidUrl, - - // === Transparent === - #[error(transparent)] - Dns(#[from] SimpleDnsError), - - #[error(transparent)] - Pkarr(#[from] pkarr::Error), - - #[error(transparent)] - Url(#[from] url::ParseError), - - #[error(transparent)] - Reqwest(#[from] reqwest::Error), - - #[error(transparent)] - Session(#[from] pubky_common::session::Error), - - #[error(transparent)] - Crypto(#[from] pubky_common::crypto::Error), - - #[error(transparent)] - RecoveryFile(#[from] pubky_common::recovery_file::Error), - - #[error(transparent)] - AuthToken(#[from] pubky_common::auth::Error), -} - -#[cfg(target_arch = "wasm32")] -use wasm_bindgen::JsValue; - -#[cfg(target_arch = "wasm32")] -impl From for JsValue { - fn from(error: Error) -> JsValue { - let error_message = error.to_string(); - js_sys::Error::new(&error_message).into() - } -} diff --git a/rust/pubky/pubky/src/lib.rs b/rust/pubky/pubky/src/lib.rs deleted file mode 100644 index 2b6cf42..0000000 --- a/rust/pubky/pubky/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -mod error; -mod shared; - -#[cfg(not(target_arch = "wasm32"))] -mod native; - -#[cfg(target_arch = "wasm32")] -mod wasm; -#[cfg(target_arch = "wasm32")] -use std::{ - collections::HashSet, - sync::{Arc, RwLock}, -}; - -use wasm_bindgen::prelude::*; - -#[cfg(not(target_arch = "wasm32"))] -use ::pkarr::PkarrClientAsync; - -pub use error::Error; - -#[cfg(not(target_arch = "wasm32"))] -pub use crate::shared::list_builder::ListBuilder; - -#[derive(Debug, Clone)] -#[wasm_bindgen] -pub struct PubkyClient { - http: reqwest::Client, - #[cfg(not(target_arch = "wasm32"))] - pub(crate) pkarr: PkarrClientAsync, - /// A cookie jar for nodejs fetch. - #[cfg(target_arch = "wasm32")] - pub(crate) session_cookies: Arc>>, - #[cfg(target_arch = "wasm32")] - pub(crate) pkarr_relays: Vec, -} diff --git a/rust/pubky/pubky/src/native.rs b/rust/pubky/pubky/src/native.rs deleted file mode 100644 index 81924ba..0000000 --- a/rust/pubky/pubky/src/native.rs +++ /dev/null @@ -1,258 +0,0 @@ -use std::net::ToSocketAddrs; -use std::time::Duration; - -use bytes::Bytes; -use pubky_common::{ - capabilities::Capabilities, - recovery_file::{create_recovery_file, decrypt_recovery_file}, - session::Session, -}; -use reqwest::{RequestBuilder, Response}; -use tokio::sync::oneshot; -use url::Url; - -use pkarr::{Keypair, PkarrClientAsync}; - -use ::pkarr::{mainline::dht::Testnet, PkarrClient, PublicKey, SignedPacket}; - -use crate::{ - error::{Error, Result}, - shared::list_builder::ListBuilder, - PubkyClient, -}; - -static DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); - -#[derive(Debug, Default)] -pub struct PubkyClientBuilder { - pkarr_settings: pkarr::Settings, -} - -impl PubkyClientBuilder { - /// Set Pkarr client [pkarr::Settings]. - pub fn pkarr_settings(mut self, settings: pkarr::Settings) -> Self { - self.pkarr_settings = settings; - self - } - - /// Use the bootstrap nodes of a testnet, as the bootstrap nodes and - /// resolvers in the internal Pkarr client. - pub fn testnet(mut self, testnet: &Testnet) -> Self { - self.pkarr_settings.dht.bootstrap = testnet.bootstrap.to_vec().into(); - - self.pkarr_settings.resolvers = testnet - .bootstrap - .iter() - .flat_map(|resolver| resolver.to_socket_addrs()) - .flatten() - .collect::>() - .into(); - - self - } - - /// Set the request_timeout of the UDP socket in the Mainline DHT client in - /// the internal Pkarr client. - /// - /// Useful to speed unit tests. - /// Defaults to 2 seconds. - pub fn dht_request_timeout(mut self, timeout: Duration) -> Self { - self.pkarr_settings.dht.request_timeout = timeout.into(); - self - } - - /// Build [PubkyClient] - pub fn build(self) -> PubkyClient { - PubkyClient { - http: reqwest::Client::builder() - .cookie_store(true) - .user_agent(DEFAULT_USER_AGENT) - .build() - .unwrap(), - pkarr: PkarrClient::new(self.pkarr_settings).unwrap().as_async(), - } - } -} - -impl Default for PubkyClient { - fn default() -> Self { - PubkyClient::builder().build() - } -} - -// === Public API === - -impl PubkyClient { - /// Returns a builder to edit settings before creating [PubkyClient]. - pub fn builder() -> PubkyClientBuilder { - PubkyClientBuilder::default() - } - - /// Create a client connected to the local network - /// with the bootstrapping node: `localhost:6881` - pub fn testnet() -> Self { - Self::test(&Testnet { - bootstrap: vec!["localhost:6881".to_string()], - nodes: vec![], - }) - } - - /// Creates a [PubkyClient] with: - /// - DHT bootstrap nodes set to the `testnet` bootstrap nodes. - /// - DHT request timout set to 500 milliseconds. (unless in CI, then it is left as default 2000) - /// - /// For more control, you can use [PubkyClientBuilder::testnet] - pub fn test(testnet: &Testnet) -> PubkyClient { - let mut builder = PubkyClient::builder().testnet(testnet); - - if std::env::var("CI").is_err() { - builder = builder.dht_request_timeout(Duration::from_millis(500)); - } - - builder.build() - } - - // === Getters === - - /// Returns a reference to the internal [pkarr] Client. - pub fn pkarr(&self) -> &PkarrClientAsync { - &self.pkarr - } - - // === Auth === - - /// Signup to a homeserver and update Pkarr accordingly. - /// - /// The homeserver is a Pkarr domain name, where the TLD is a Pkarr public key - /// for example "pubky.o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy" - pub async fn signup(&self, keypair: &Keypair, homeserver: &PublicKey) -> Result { - self.inner_signup(keypair, homeserver).await - } - - /// Check the current sesison for a given Pubky in its homeserver. - /// - /// Returns [Session] or `None` (if recieved `404 NOT_FOUND`), - /// or [reqwest::Error] if the response has any other `>=400` status code. - pub async fn session(&self, pubky: &PublicKey) -> Result> { - self.inner_session(pubky).await - } - - /// Signout from a homeserver. - pub async fn signout(&self, pubky: &PublicKey) -> Result<()> { - self.inner_signout(pubky).await - } - - /// Signin to a homeserver. - pub async fn signin(&self, keypair: &Keypair) -> Result { - self.inner_signin(keypair).await - } - - // === Public data === - - /// Upload a small payload to a given path. - pub async fn put>(&self, url: T, content: &[u8]) -> Result<()> { - self.inner_put(url, content).await - } - - /// Download a small payload from a given path relative to a pubky author. - pub async fn get>(&self, url: T) -> Result> { - self.inner_get(url).await - } - - /// Delete a file at a path relative to a pubky author. - pub async fn delete>(&self, url: T) -> Result<()> { - self.inner_delete(url).await - } - - /// Returns a [ListBuilder] to help pass options before calling [ListBuilder::send]. - /// - /// `url` sets the path you want to lest within. - pub fn list>(&self, url: T) -> Result { - self.inner_list(url) - } - - // === Helpers === - - /// Create a recovery file of the `keypair`, containing the secret key encrypted - /// using the `passphrase`. - pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result> { - Ok(create_recovery_file(keypair, passphrase)?) - } - - /// Recover a keypair from a recovery file by decrypting the secret key using `passphrase`. - pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result { - Ok(decrypt_recovery_file(recovery_file, passphrase)?) - } - - /// Return `pubkyauth://` url and wait for the incoming [AuthToken] - /// verifying that AuthToken, and if capabilities were requested, signing in to - /// the Pubky's homeserver and returning the [Session] information. - pub fn auth_request( - &self, - relay: impl TryInto, - capabilities: &Capabilities, - ) -> Result<(Url, tokio::sync::oneshot::Receiver)> { - let mut relay: Url = relay - .try_into() - .map_err(|_| Error::Generic("Invalid relay Url".into()))?; - - let (pubkyauth_url, client_secret) = self.create_auth_request(&mut relay, capabilities)?; - - let (tx, rx) = oneshot::channel::(); - - let this = self.clone(); - - tokio::spawn(async move { - let to_send = this - .subscribe_to_auth_response(relay, &client_secret) - .await?; - - tx.send(to_send) - .map_err(|_| Error::Generic("Failed to send the session after signing in with token, since the receiver is dropped".into()))?; - - Ok::<(), Error>(()) - }); - - Ok((pubkyauth_url, rx)) - } - - /// Sign an [pubky_common::auth::AuthToken], encrypt it and send it to the - /// source of the pubkyauth request url. - pub async fn send_auth_token>( - &self, - keypair: &Keypair, - pubkyauth_url: T, - ) -> Result<()> { - let url: Url = pubkyauth_url.try_into().map_err(|_| Error::InvalidUrl)?; - - self.inner_send_auth_token(keypair, url).await?; - - Ok(()) - } -} - -// === Internals === - -impl PubkyClient { - // === Pkarr === - - pub(crate) async fn pkarr_resolve( - &self, - public_key: &PublicKey, - ) -> Result> { - Ok(self.pkarr.resolve(public_key).await?) - } - - pub(crate) async fn pkarr_publish(&self, signed_packet: &SignedPacket) -> Result<()> { - Ok(self.pkarr.publish(signed_packet).await?) - } - - // === HTTP === - - pub(crate) fn request(&self, method: reqwest::Method, url: Url) -> RequestBuilder { - self.http.request(method, url) - } - - pub(crate) fn store_session(&self, _: &Response) {} - pub(crate) fn remove_session(&self, _: &PublicKey) {} -} diff --git a/rust/pubky/pubky/src/shared/auth.rs b/rust/pubky/pubky/src/shared/auth.rs deleted file mode 100644 index aa8cfa9..0000000 --- a/rust/pubky/pubky/src/shared/auth.rs +++ /dev/null @@ -1,341 +0,0 @@ -use std::collections::HashMap; - -use base64::{alphabet::URL_SAFE, engine::general_purpose::NO_PAD, Engine}; -use reqwest::{Method, StatusCode}; -use url::Url; - -use pkarr::{Keypair, PublicKey}; -use pubky_common::{ - auth::AuthToken, - capabilities::{Capabilities, Capability}, - crypto::{decrypt, encrypt, hash, random_bytes}, - session::Session, -}; - -use crate::{ - error::{Error, Result}, - PubkyClient, -}; - -use super::pkarr::Endpoint; - -impl PubkyClient { - /// Signup to a homeserver and update Pkarr accordingly. - /// - /// The homeserver is a Pkarr domain name, where the TLD is a Pkarr public key - /// for example "pubky.o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy" - pub(crate) async fn inner_signup( - &self, - keypair: &Keypair, - homeserver: &PublicKey, - ) -> Result { - let homeserver = homeserver.to_string(); - - let Endpoint { mut url, .. } = self.resolve_endpoint(&homeserver).await?; - - url.set_path("/signup"); - - let body = AuthToken::sign(keypair, vec![Capability::root()]).serialize(); - - let response = self - .request(Method::POST, url.clone()) - .body(body) - .send() - .await?; - - self.store_session(&response); - - self.publish_pubky_homeserver(keypair, &homeserver).await?; - - let bytes = response.bytes().await?; - - Ok(Session::deserialize(&bytes)?) - } - - /// Check the current sesison for a given Pubky in its homeserver. - /// - /// Returns None if not signed in, or [reqwest::Error] - /// if the response has any other `>=404` status code. - pub(crate) async fn inner_session(&self, pubky: &PublicKey) -> Result> { - let Endpoint { mut url, .. } = self.resolve_pubky_homeserver(pubky).await?; - - url.set_path(&format!("/{}/session", pubky)); - - let res = self.request(Method::GET, url).send().await?; - - if res.status() == StatusCode::NOT_FOUND { - return Ok(None); - } - - if !res.status().is_success() { - res.error_for_status_ref()?; - }; - - let bytes = res.bytes().await?; - - Ok(Some(Session::deserialize(&bytes)?)) - } - - /// Signout from a homeserver. - pub(crate) async fn inner_signout(&self, pubky: &PublicKey) -> Result<()> { - let Endpoint { mut url, .. } = self.resolve_pubky_homeserver(pubky).await?; - - url.set_path(&format!("/{}/session", pubky)); - - self.request(Method::DELETE, url).send().await?; - - self.remove_session(pubky); - - Ok(()) - } - - /// Signin to a homeserver. - pub(crate) async fn inner_signin(&self, keypair: &Keypair) -> Result { - let token = AuthToken::sign(keypair, vec![Capability::root()]); - - self.signin_with_authtoken(&token).await - } - - pub(crate) async fn inner_send_auth_token( - &self, - keypair: &Keypair, - pubkyauth_url: Url, - ) -> Result<()> { - let query_params: HashMap = - pubkyauth_url.query_pairs().into_owned().collect(); - - let relay = query_params - .get("relay") - .map(|r| url::Url::parse(r).expect("Relay query param to be valid URL")) - .expect("Missing relay query param"); - - let client_secret = query_params - .get("secret") - .map(|s| { - let engine = base64::engine::GeneralPurpose::new(&URL_SAFE, NO_PAD); - let bytes = engine.decode(s).expect("invalid client_secret"); - let arr: [u8; 32] = bytes.try_into().expect("invalid client_secret"); - - arr - }) - .expect("Missing client secret"); - - let capabilities = query_params - .get("caps") - .map(|caps_string| { - caps_string - .split(',') - .filter_map(|cap| Capability::try_from(cap).ok()) - .collect::>() - }) - .unwrap_or_default(); - - let token = AuthToken::sign(keypair, capabilities); - - let encrypted_token = encrypt(&token.serialize(), &client_secret)?; - - let engine = base64::engine::GeneralPurpose::new(&URL_SAFE, NO_PAD); - - let mut callback = relay.clone(); - let mut path_segments = callback.path_segments_mut().unwrap(); - path_segments.pop_if_empty(); - let channel_id = engine.encode(hash(&client_secret).as_bytes()); - path_segments.push(&channel_id); - drop(path_segments); - - self.request(Method::POST, callback) - .body(encrypted_token) - .send() - .await?; - - Ok(()) - } - - pub async fn inner_third_party_signin( - &self, - encrypted_token: &[u8], - client_secret: &[u8; 32], - ) -> Result { - let decrypted = decrypt(encrypted_token, client_secret)?; - let token = AuthToken::deserialize(&decrypted)?; - - self.signin_with_authtoken(&token).await?; - - Ok(token.pubky().to_owned()) - } - - pub async fn signin_with_authtoken(&self, token: &AuthToken) -> Result { - let mut url = Url::parse(&format!("https://{}/session", token.pubky()))?; - - self.resolve_url(&mut url).await?; - - let response = self - .request(Method::POST, url) - .body(token.serialize()) - .send() - .await?; - - self.store_session(&response); - - let bytes = response.bytes().await?; - - Ok(Session::deserialize(&bytes)?) - } - - pub(crate) fn create_auth_request( - &self, - relay: &mut Url, - capabilities: &Capabilities, - ) -> Result<(Url, [u8; 32])> { - let engine = base64::engine::GeneralPurpose::new(&URL_SAFE, NO_PAD); - - let client_secret: [u8; 32] = random_bytes::<32>(); - - let pubkyauth_url = Url::parse(&format!( - "pubkyauth:///?caps={capabilities}&secret={}&relay={relay}", - engine.encode(client_secret) - ))?; - - let mut segments = relay - .path_segments_mut() - .map_err(|_| Error::Generic("Invalid relay".into()))?; - // remove trailing slash if any. - segments.pop_if_empty(); - let channel_id = &engine.encode(hash(&client_secret).as_bytes()); - segments.push(channel_id); - drop(segments); - - Ok((pubkyauth_url, client_secret)) - } - - pub(crate) async fn subscribe_to_auth_response( - &self, - relay: Url, - client_secret: &[u8; 32], - ) -> Result { - let response = self.http.request(Method::GET, relay).send().await?; - let encrypted_token = response.bytes().await?; - let token_bytes = decrypt(&encrypted_token, client_secret)?; - let token = AuthToken::verify(&token_bytes)?; - - if !token.capabilities().is_empty() { - self.signin_with_authtoken(&token).await?; - } - - Ok(token.pubky().clone()) - } -} - -#[cfg(test)] -mod tests { - - use crate::*; - - use pkarr::{mainline::Testnet, Keypair}; - use pubky_common::capabilities::{Capabilities, Capability}; - use pubky_homeserver::Homeserver; - use reqwest::StatusCode; - - #[tokio::test] - async fn basic_authn() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let session = client - .session(&keypair.public_key()) - .await - .unwrap() - .unwrap(); - - assert!(session.capabilities().contains(&Capability::root())); - - client.signout(&keypair.public_key()).await.unwrap(); - - { - let session = client.session(&keypair.public_key()).await.unwrap(); - - assert!(session.is_none()); - } - - client.signin(&keypair).await.unwrap(); - - { - let session = client - .session(&keypair.public_key()) - .await - .unwrap() - .unwrap(); - - assert_eq!(session.pubky(), &keypair.public_key()); - assert!(session.capabilities().contains(&Capability::root())); - } - } - - #[tokio::test] - async fn authz() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let keypair = Keypair::random(); - let pubky = keypair.public_key(); - - // Third party app side - let capabilities: Capabilities = - "/pub/pubky.app/:rw,/pub/foo.bar/file:r".try_into().unwrap(); - let client = PubkyClient::test(&testnet); - let (pubkyauth_url, pubkyauth_response) = client - .auth_request("https://demo.httprelay.io/link", &capabilities) - .unwrap(); - - // Authenticator side - { - let client = PubkyClient::test(&testnet); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - client - .send_auth_token(&keypair, pubkyauth_url) - .await - .unwrap(); - } - - let public_key = pubkyauth_response.await.unwrap(); - - assert_eq!(&public_key, &pubky); - - // Test access control enforcement - - client - .put(format!("pubky://{pubky}/pub/pubky.app/foo").as_str(), &[]) - .await - .unwrap(); - - assert_eq!( - client - .put(format!("pubky://{pubky}/pub/pubky.app").as_str(), &[]) - .await - .map_err(|e| match e { - crate::Error::Reqwest(e) => e.status(), - _ => None, - }), - Err(Some(StatusCode::FORBIDDEN)) - ); - - assert_eq!( - client - .put(format!("pubky://{pubky}/pub/foo.bar/file").as_str(), &[]) - .await - .map_err(|e| match e { - crate::Error::Reqwest(e) => e.status(), - _ => None, - }), - Err(Some(StatusCode::FORBIDDEN)) - ); - } -} diff --git a/rust/pubky/pubky/src/shared/list_builder.rs b/rust/pubky/pubky/src/shared/list_builder.rs deleted file mode 100644 index 0eaec77..0000000 --- a/rust/pubky/pubky/src/shared/list_builder.rs +++ /dev/null @@ -1,105 +0,0 @@ -use reqwest::Method; -use url::Url; - -use crate::{error::Result, PubkyClient}; - -#[derive(Debug)] -pub struct ListBuilder<'a> { - url: Url, - reverse: bool, - limit: Option, - cursor: Option<&'a str>, - client: &'a PubkyClient, - shallow: bool, -} - -impl<'a> ListBuilder<'a> { - /// Create a new List request builder - pub(crate) fn new(client: &'a PubkyClient, url: Url) -> Self { - Self { - client, - url, - limit: None, - cursor: None, - reverse: false, - shallow: false, - } - } - - /// Set the `reverse` option. - pub fn reverse(mut self, reverse: bool) -> Self { - self.reverse = reverse; - self - } - - /// Set the `limit` value. - pub fn limit(mut self, limit: u16) -> Self { - self.limit = limit.into(); - self - } - - /// Set the `cursor` value. - /// - /// Either a full `pubky://` Url (from previous list response), - /// or a path (to a file or directory) relative to the `url` - pub fn cursor(mut self, cursor: &'a str) -> Self { - self.cursor = cursor.into(); - self - } - - pub fn shallow(mut self, shallow: bool) -> Self { - self.shallow = shallow; - self - } - - /// Send the list request. - /// - /// Returns a list of Pubky URLs of the files in the path of the `url` - /// respecting [ListBuilder::reverse], [ListBuilder::limit] and [ListBuilder::cursor] - /// options. - pub async fn send(self) -> Result> { - let mut url = self.client.pubky_to_http(self.url).await?; - - if !url.path().ends_with('/') { - let path = url.path().to_string(); - let mut parts = path.split('/').collect::>(); - parts.pop(); - - let path = format!("{}/", parts.join("/")); - - url.set_path(&path) - } - - let mut query = url.query_pairs_mut(); - - if self.reverse { - query.append_key_only("reverse"); - } - - if self.shallow { - query.append_key_only("shallow"); - } - - if let Some(limit) = self.limit { - query.append_pair("limit", &limit.to_string()); - } - - if let Some(cursor) = self.cursor { - query.append_pair("cursor", cursor); - } - - drop(query); - - let response = self.client.request(Method::GET, url).send().await?; - - response.error_for_status_ref()?; - - // TODO: bail on too large files. - let bytes = response.bytes().await?; - - Ok(String::from_utf8_lossy(&bytes) - .lines() - .map(String::from) - .collect()) - } -} diff --git a/rust/pubky/pubky/src/shared/mod.rs b/rust/pubky/pubky/src/shared/mod.rs deleted file mode 100644 index 67b456f..0000000 --- a/rust/pubky/pubky/src/shared/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod auth; -pub mod list_builder; -pub mod pkarr; -pub mod public; diff --git a/rust/pubky/pubky/src/shared/pkarr.rs b/rust/pubky/pubky/src/shared/pkarr.rs deleted file mode 100644 index 85055ef..0000000 --- a/rust/pubky/pubky/src/shared/pkarr.rs +++ /dev/null @@ -1,336 +0,0 @@ -use url::Url; - -use pkarr::{ - dns::{rdata::SVCB, Packet}, - Keypair, PublicKey, SignedPacket, -}; - -use crate::{ - error::{Error, Result}, - PubkyClient, -}; - -const MAX_ENDPOINT_RESOLUTION_RECURSION: u8 = 3; - -impl PubkyClient { - /// Publish the SVCB record for `_pubky.`. - pub(crate) async fn publish_pubky_homeserver( - &self, - keypair: &Keypair, - host: &str, - ) -> Result<()> { - let existing = self.pkarr_resolve(&keypair.public_key()).await?; - - let mut packet = Packet::new_reply(0); - - if let Some(existing) = existing { - for answer in existing.packet().answers.iter().cloned() { - if !answer.name.to_string().starts_with("_pubky") { - packet.answers.push(answer.into_owned()) - } - } - } - - let svcb = SVCB::new(0, host.try_into()?); - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "_pubky".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), - )); - - let signed_packet = SignedPacket::from_packet(keypair, &packet)?; - - self.pkarr_publish(&signed_packet).await?; - - Ok(()) - } - - /// Resolve the homeserver for a pubky. - pub(crate) async fn resolve_pubky_homeserver(&self, pubky: &PublicKey) -> Result { - let target = format!("_pubky.{pubky}"); - - self.resolve_endpoint(&target) - .await - .map_err(|_| Error::Generic("Could not resolve homeserver".to_string())) - } - - /// Resolve a service's public_key and "non-pkarr url" from a Pubky domain - /// - /// "non-pkarr" url is any URL where the hostname isn't a 52 z-base32 character, - /// usually an IPv4, IPv6 or ICANN domain, but could also be any other unknown hostname. - /// - /// Recursively resolve SVCB and HTTPS endpoints, with [MAX_ENDPOINT_RESOLUTION_RECURSION] limit. - pub(crate) async fn resolve_endpoint(&self, target: &str) -> Result { - let original_target = target; - // TODO: cache the result of this function? - - let mut target = target.to_string(); - - let mut endpoint_public_key = None; - let mut origin = target.clone(); - - let mut step = 0; - - // PublicKey is very good at extracting the Pkarr TLD from a string. - while let Ok(public_key) = PublicKey::try_from(target.clone()) { - if step >= MAX_ENDPOINT_RESOLUTION_RECURSION { - break; - }; - step += 1; - - if let Some(signed_packet) = self - .pkarr_resolve(&public_key) - .await - .map_err(|_| Error::ResolveEndpoint(original_target.into()))? - { - // Choose most prior SVCB record - let svcb = signed_packet.resource_records(&target).fold( - None, - |prev: Option, answer| { - if let Some(svcb) = match &answer.rdata { - pkarr::dns::rdata::RData::SVCB(svcb) => Some(svcb), - pkarr::dns::rdata::RData::HTTPS(curr) => Some(&curr.0), - _ => None, - } { - let curr = svcb.clone(); - - if curr.priority == 0 { - return Some(curr); - } - if let Some(prev) = &prev { - // TODO return random if priority is the same - if curr.priority >= prev.priority { - return Some(curr); - } - } else { - return Some(curr); - } - } - - prev - }, - ); - - if let Some(svcb) = svcb { - endpoint_public_key = Some(public_key.clone()); - target = svcb.target.to_string(); - - if let Some(port) = svcb.get_param(pkarr::dns::rdata::SVCB::PORT) { - if port.len() < 2 { - // TODO: debug! Error encoding port! - } - let port = u16::from_be_bytes([port[0], port[1]]); - - origin = format!("{target}:{port}"); - } else { - origin.clone_from(&target); - }; - - if step >= MAX_ENDPOINT_RESOLUTION_RECURSION { - continue; - }; - } - } else { - break; - } - } - - if PublicKey::try_from(origin.as_str()).is_ok() { - return Err(Error::ResolveEndpoint(original_target.into())); - } - - if endpoint_public_key.is_some() { - let url = Url::parse(&format!( - "{}://{}", - if origin.starts_with("localhost") { - "http" - } else { - "https" - }, - origin - ))?; - - return Ok(Endpoint { url }); - } - - Err(Error::ResolveEndpoint(original_target.into())) - } - - pub(crate) async fn resolve_url(&self, url: &mut Url) -> Result<()> { - if let Some(Ok(pubky)) = url.host_str().map(PublicKey::try_from) { - let Endpoint { url: x, .. } = self.resolve_endpoint(&format!("_pubky.{pubky}")).await?; - - url.set_host(x.host_str())?; - url.set_port(x.port()).expect("should work!"); - url.set_scheme(x.scheme()).expect("should work!"); - }; - - Ok(()) - } -} - -#[derive(Debug)] -pub(crate) struct Endpoint { - pub url: Url, -} - -#[cfg(test)] -mod tests { - use super::*; - - use pkarr::{ - dns::{ - rdata::{HTTPS, SVCB}, - Packet, - }, - mainline::{dht::DhtSettings, Testnet}, - Keypair, PkarrClient, Settings, SignedPacket, - }; - use pubky_homeserver::Homeserver; - - #[tokio::test] - async fn resolve_endpoint_https() { - let testnet = Testnet::new(10); - - let pkarr_client = PkarrClient::new(Settings { - dht: DhtSettings { - bootstrap: Some(testnet.bootstrap.clone()), - ..Default::default() - }, - ..Default::default() - }) - .unwrap() - .as_async(); - - let domain = "example.com"; - let mut target; - - // Server - { - let keypair = Keypair::random(); - - let https = HTTPS(SVCB::new(0, domain.try_into().unwrap())); - - let mut packet = Packet::new_reply(0); - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "foo".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::HTTPS(https), - )); - - let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap(); - - pkarr_client.publish(&signed_packet).await.unwrap(); - - target = format!("foo.{}", keypair.public_key()); - } - - // intermediate - { - let keypair = Keypair::random(); - - let svcb = SVCB::new(0, target.as_str().try_into().unwrap()); - - let mut packet = Packet::new_reply(0); - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "bar".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), - )); - - let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap(); - - pkarr_client.publish(&signed_packet).await.unwrap(); - - target = format!("bar.{}", keypair.public_key()) - } - - { - let keypair = Keypair::random(); - - let svcb = SVCB::new(0, target.as_str().try_into().unwrap()); - - let mut packet = Packet::new_reply(0); - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "pubky".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), - )); - - let signed_packet = SignedPacket::from_packet(&keypair, &packet).unwrap(); - - pkarr_client.publish(&signed_packet).await.unwrap(); - - target = format!("pubky.{}", keypair.public_key()) - } - - let client = PubkyClient::test(&testnet); - - let endpoint = client.resolve_endpoint(&target).await.unwrap(); - - assert_eq!(endpoint.url.host_str().unwrap(), domain); - } - - #[tokio::test] - async fn resolve_homeserver() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - // Publish an intermediate controller of the homeserver - let pkarr_client = PkarrClient::new(Settings { - dht: DhtSettings { - bootstrap: Some(testnet.bootstrap.clone()), - ..Default::default() - }, - ..Default::default() - }) - .unwrap() - .as_async(); - - let intermediate = Keypair::random(); - - let mut packet = Packet::new_reply(0); - - let server_tld = server.public_key().to_string(); - - let svcb = SVCB::new(0, server_tld.as_str().try_into().unwrap()); - - packet.answers.push(pkarr::dns::ResourceRecord::new( - "pubky".try_into().unwrap(), - pkarr::dns::CLASS::IN, - 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), - )); - - let signed_packet = SignedPacket::from_packet(&intermediate, &packet).unwrap(); - - pkarr_client.publish(&signed_packet).await.unwrap(); - - { - let client = PubkyClient::test(&testnet); - - let pubky = Keypair::random(); - - client - .publish_pubky_homeserver(&pubky, &format!("pubky.{}", &intermediate.public_key())) - .await - .unwrap(); - - let Endpoint { url, .. } = client - .resolve_pubky_homeserver(&pubky.public_key()) - .await - .unwrap(); - - assert_eq!(url.host_str(), Some("localhost")); - assert_eq!(url.port(), Some(server.port())); - } - } -} diff --git a/rust/pubky/pubky/src/shared/public.rs b/rust/pubky/pubky/src/shared/public.rs deleted file mode 100644 index becf2fb..0000000 --- a/rust/pubky/pubky/src/shared/public.rs +++ /dev/null @@ -1,824 +0,0 @@ -use bytes::Bytes; - -use pkarr::PublicKey; -use reqwest::{Method, StatusCode}; -use url::Url; - -use crate::{ - error::{Error, Result}, - PubkyClient, -}; - -use super::{list_builder::ListBuilder, pkarr::Endpoint}; - -impl PubkyClient { - pub(crate) async fn inner_put>(&self, url: T, content: &[u8]) -> Result<()> { - let url = self.pubky_to_http(url).await?; - - let response = self - .request(Method::PUT, url) - .body(content.to_owned()) - .send() - .await?; - - response.error_for_status()?; - - Ok(()) - } - - pub(crate) async fn inner_get>(&self, url: T) -> Result> { - let url = self.pubky_to_http(url).await?; - - let response = self.request(Method::GET, url).send().await?; - - if response.status() == StatusCode::NOT_FOUND { - return Ok(None); - } - - response.error_for_status_ref()?; - - // TODO: bail on too large files. - let bytes = response.bytes().await?; - - Ok(Some(bytes)) - } - - pub(crate) async fn inner_delete>(&self, url: T) -> Result<()> { - let url = self.pubky_to_http(url).await?; - - let response = self.request(Method::DELETE, url).send().await?; - - response.error_for_status_ref()?; - - Ok(()) - } - - pub(crate) fn inner_list>(&self, url: T) -> Result { - Ok(ListBuilder::new( - self, - url.try_into().map_err(|_| Error::InvalidUrl)?, - )) - } - - pub(crate) async fn pubky_to_http>(&self, url: T) -> Result { - let original_url: Url = url.try_into().map_err(|_| Error::InvalidUrl)?; - - let pubky = original_url - .host_str() - .ok_or(Error::Generic("Missing Pubky Url host".to_string()))?; - - if let Ok(public_key) = PublicKey::try_from(pubky) { - let Endpoint { mut url, .. } = self.resolve_pubky_homeserver(&public_key).await?; - - // TODO: remove if we move to subdomains instead of paths. - if original_url.scheme() == "pubky" { - let path = original_url.path_segments(); - - let mut split = url.path_segments_mut().unwrap(); - split.push(pubky); - if let Some(segments) = path { - for segment in segments { - split.push(segment); - } - } - drop(split); - } - - return Ok(url); - } - - Ok(original_url) - } -} - -#[cfg(test)] -mod tests { - - use core::panic; - - use crate::*; - - use pkarr::{mainline::Testnet, Keypair}; - use pubky_homeserver::Homeserver; - use reqwest::{Method, StatusCode}; - - #[tokio::test] - async fn put_get_delete() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let url = format!("pubky://{}/pub/foo.txt", keypair.public_key()); - let url = url.as_str(); - - client.put(url, &[0, 1, 2, 3, 4]).await.unwrap(); - - let response = client.get(url).await.unwrap().unwrap(); - - assert_eq!(response, bytes::Bytes::from(vec![0, 1, 2, 3, 4])); - - client.delete(url).await.unwrap(); - - let response = client.get(url).await.unwrap(); - - assert_eq!(response, None); - } - - #[tokio::test] - async fn unauthorized_put_delete() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let public_key = keypair.public_key(); - - let url = format!("pubky://{public_key}/pub/foo.txt"); - let url = url.as_str(); - - let other_client = PubkyClient::test(&testnet); - { - let other = Keypair::random(); - - // TODO: remove extra client after switching to subdomains. - other_client - .signup(&other, &server.public_key()) - .await - .unwrap(); - - let response = other_client.put(url, &[0, 1, 2, 3, 4]).await; - - match response { - Err(Error::Reqwest(error)) => { - assert!(error.status() == Some(StatusCode::UNAUTHORIZED)) - } - _ => { - panic!("expected error StatusCode::UNAUTHORIZED") - } - } - } - - client.put(url, &[0, 1, 2, 3, 4]).await.unwrap(); - - { - let other = Keypair::random(); - - // TODO: remove extra client after switching to subdomains. - other_client - .signup(&other, &server.public_key()) - .await - .unwrap(); - - let response = other_client.delete(url).await; - - match response { - Err(Error::Reqwest(error)) => { - assert!(error.status() == Some(StatusCode::UNAUTHORIZED)) - } - _ => { - panic!("expected error StatusCode::UNAUTHORIZED") - } - } - } - - let response = client.get(url).await.unwrap().unwrap(); - - assert_eq!(response, bytes::Bytes::from(vec![0, 1, 2, 3, 4])); - } - - #[tokio::test] - async fn list() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let pubky = keypair.public_key(); - - let urls = vec![ - format!("pubky://{pubky}/pub/a.wrong/a.txt"), - format!("pubky://{pubky}/pub/example.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - format!("pubky://{pubky}/pub/example.wrong/a.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - format!("pubky://{pubky}/pub/example.com/d.txt"), - format!("pubky://{pubky}/pub/z.wrong/a.txt"), - ]; - - for url in urls { - client.put(url.as_str(), &[0]).await.unwrap(); - } - - let url = format!("pubky://{pubky}/pub/example.com/extra"); - let url = url.as_str(); - - { - let list = client.list(url).unwrap().send().await.unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - format!("pubky://{pubky}/pub/example.com/d.txt"), - ], - "normal list with no limit or cursor" - ); - } - - { - let list = client.list(url).unwrap().limit(2).send().await.unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - ], - "normal list with limit but no cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .limit(2) - .cursor("a.txt") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - ], - "normal list with limit and a file cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .limit(2) - .cursor("cc-nested/") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - format!("pubky://{pubky}/pub/example.com/d.txt"), - ], - "normal list with limit and a directory cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .limit(2) - .cursor(&format!("pubky://{pubky}/pub/example.com/a.txt")) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - ], - "normal list with limit and a full url cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .limit(2) - .cursor("/a.txt") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - ], - "normal list with limit and a leading / cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .reverse(true) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/d.txt"), - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/a.txt"), - ], - "reverse list with no limit or cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .reverse(true) - .limit(2) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/d.txt"), - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - ], - "reverse list with limit but no cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .reverse(true) - .limit(2) - .cursor("d.txt") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/cc-nested/z.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - ], - "reverse list with limit and cursor" - ); - } - } - - #[tokio::test] - async fn list_shallow() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let pubky = keypair.public_key(); - - let urls = vec![ - format!("pubky://{pubky}/pub/a.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - format!("pubky://{pubky}/pub/example.com/d.txt"), - format!("pubky://{pubky}/pub/example.con/d.txt"), - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/file"), - format!("pubky://{pubky}/pub/file2"), - format!("pubky://{pubky}/pub/z.com/a.txt"), - ]; - - for url in urls { - client.put(url.as_str(), &[0]).await.unwrap(); - } - - let url = format!("pubky://{pubky}/pub/"); - let url = url.as_str(); - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/a.com/"), - format!("pubky://{pubky}/pub/example.com/"), - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/example.con/"), - format!("pubky://{pubky}/pub/file"), - format!("pubky://{pubky}/pub/file2"), - format!("pubky://{pubky}/pub/z.com/"), - ], - "normal list shallow" - ); - } - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .limit(2) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/a.com/"), - format!("pubky://{pubky}/pub/example.com/"), - ], - "normal list shallow with limit but no cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .limit(2) - .cursor("example.com/a.txt") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.com/"), - format!("pubky://{pubky}/pub/example.con"), - ], - "normal list shallow with limit and a file cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .limit(3) - .cursor("example.com/") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/example.con/"), - format!("pubky://{pubky}/pub/file"), - ], - "normal list shallow with limit and a directory cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .reverse(true) - .shallow(true) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/z.com/"), - format!("pubky://{pubky}/pub/file2"), - format!("pubky://{pubky}/pub/file"), - format!("pubky://{pubky}/pub/example.con/"), - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/example.com/"), - format!("pubky://{pubky}/pub/a.com/"), - ], - "reverse list shallow" - ); - } - - { - let list = client - .list(url) - .unwrap() - .reverse(true) - .shallow(true) - .limit(2) - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/z.com/"), - format!("pubky://{pubky}/pub/file2"), - ], - "reverse list shallow with limit but no cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .reverse(true) - .limit(2) - .cursor("file2") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/file"), - format!("pubky://{pubky}/pub/example.con/"), - ], - "reverse list shallow with limit and a file cursor" - ); - } - - { - let list = client - .list(url) - .unwrap() - .shallow(true) - .reverse(true) - .limit(2) - .cursor("example.con/") - .send() - .await - .unwrap(); - - assert_eq!( - list, - vec![ - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/example.com/"), - ], - "reverse list shallow with limit and a directory cursor" - ); - } - } - - #[tokio::test] - async fn list_events() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let pubky = keypair.public_key(); - - let urls = vec![ - format!("pubky://{pubky}/pub/a.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/a.txt"), - format!("pubky://{pubky}/pub/example.com/b.txt"), - format!("pubky://{pubky}/pub/example.com/c.txt"), - format!("pubky://{pubky}/pub/example.com/d.txt"), - format!("pubky://{pubky}/pub/example.con/d.txt"), - format!("pubky://{pubky}/pub/example.con"), - format!("pubky://{pubky}/pub/file"), - format!("pubky://{pubky}/pub/file2"), - format!("pubky://{pubky}/pub/z.com/a.txt"), - ]; - - for url in urls { - client.put(url.as_str(), &[0]).await.unwrap(); - client.delete(url.as_str()).await.unwrap(); - } - - let feed_url = format!("http://localhost:{}/events/", server.port()); - let feed_url = feed_url.as_str(); - - let client = PubkyClient::test(&testnet); - - let cursor; - - { - let response = client - .request( - Method::GET, - format!("{feed_url}?limit=10").as_str().try_into().unwrap(), - ) - .send() - .await - .unwrap(); - - let text = response.text().await.unwrap(); - let lines = text.split('\n').collect::>(); - - cursor = lines.last().unwrap().split(" ").last().unwrap().to_string(); - - assert_eq!( - lines, - vec![ - format!("PUT pubky://{pubky}/pub/a.com/a.txt"), - format!("DEL pubky://{pubky}/pub/a.com/a.txt"), - format!("PUT pubky://{pubky}/pub/example.com/a.txt"), - format!("DEL pubky://{pubky}/pub/example.com/a.txt"), - format!("PUT pubky://{pubky}/pub/example.com/b.txt"), - format!("DEL pubky://{pubky}/pub/example.com/b.txt"), - format!("PUT pubky://{pubky}/pub/example.com/c.txt"), - format!("DEL pubky://{pubky}/pub/example.com/c.txt"), - format!("PUT pubky://{pubky}/pub/example.com/d.txt"), - format!("DEL pubky://{pubky}/pub/example.com/d.txt"), - format!("cursor: {cursor}",) - ] - ); - } - - { - let response = client - .request( - Method::GET, - format!("{feed_url}?limit=10&cursor={cursor}") - .as_str() - .try_into() - .unwrap(), - ) - .send() - .await - .unwrap(); - - let text = response.text().await.unwrap(); - let lines = text.split('\n').collect::>(); - - assert_eq!( - lines, - vec![ - format!("PUT pubky://{pubky}/pub/example.con/d.txt"), - format!("DEL pubky://{pubky}/pub/example.con/d.txt"), - format!("PUT pubky://{pubky}/pub/example.con"), - format!("DEL pubky://{pubky}/pub/example.con"), - format!("PUT pubky://{pubky}/pub/file"), - format!("DEL pubky://{pubky}/pub/file"), - format!("PUT pubky://{pubky}/pub/file2"), - format!("DEL pubky://{pubky}/pub/file2"), - format!("PUT pubky://{pubky}/pub/z.com/a.txt"), - format!("DEL pubky://{pubky}/pub/z.com/a.txt"), - lines.last().unwrap().to_string() - ] - ) - } - } - - #[tokio::test] - async fn read_after_event() { - let testnet = Testnet::new(10); - let server = Homeserver::start_test(&testnet).await.unwrap(); - - let client = PubkyClient::test(&testnet); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server.public_key()).await.unwrap(); - - let pubky = keypair.public_key(); - - let url = format!("pubky://{pubky}/pub/a.com/a.txt"); - - client.put(url.as_str(), &[0]).await.unwrap(); - - let feed_url = format!("http://localhost:{}/events/", server.port()); - let feed_url = feed_url.as_str(); - - let client = PubkyClient::test(&testnet); - - { - let response = client - .request( - Method::GET, - format!("{feed_url}?limit=10").as_str().try_into().unwrap(), - ) - .send() - .await - .unwrap(); - - let text = response.text().await.unwrap(); - let lines = text.split('\n').collect::>(); - - let cursor = lines.last().unwrap().split(" ").last().unwrap().to_string(); - - assert_eq!( - lines, - vec![ - format!("PUT pubky://{pubky}/pub/a.com/a.txt"), - format!("cursor: {cursor}",) - ] - ); - } - - let get = client.get(url.as_str()).await.unwrap(); - dbg!(get); - } - - #[tokio::test] - async fn dont_delete_shared_blobs() { - let testnet = Testnet::new(10); - let homeserver = Homeserver::start_test(&testnet).await.unwrap(); - let client = PubkyClient::test(&testnet); - - let homeserver_pubky = homeserver.public_key(); - - let user_1 = Keypair::random(); - let user_2 = Keypair::random(); - - client.signup(&user_1, &homeserver_pubky).await.unwrap(); - client.signup(&user_2, &homeserver_pubky).await.unwrap(); - - let user_1_id = user_1.public_key(); - let user_2_id = user_2.public_key(); - - let url_1 = format!("pubky://{user_1_id}/pub/pubky.app/file/file_1"); - let url_2 = format!("pubky://{user_2_id}/pub/pubky.app/file/file_1"); - - let file = vec![1]; - client.put(url_1.as_str(), &file).await.unwrap(); - client.put(url_2.as_str(), &file).await.unwrap(); - - // Delete file 1 - client.delete(url_1.as_str()).await.unwrap(); - - let blob = client.get(url_2.as_str()).await.unwrap().unwrap(); - - assert_eq!(blob, file); - - let feed_url = format!("http://localhost:{}/events/", homeserver.port()); - - let response = client - .request( - Method::GET, - format!("{feed_url}").as_str().try_into().unwrap(), - ) - .send() - .await - .unwrap(); - - let text = response.text().await.unwrap(); - let lines = text.split('\n').collect::>(); - - assert_eq!( - lines, - vec![ - format!("PUT pubky://{user_1_id}/pub/pubky.app/file/file_1",), - format!("PUT pubky://{user_2_id}/pub/pubky.app/file/file_1",), - format!("DEL pubky://{user_1_id}/pub/pubky.app/file/file_1",), - lines.last().unwrap().to_string() - ] - ) - } -} diff --git a/rust/pubky/pubky/src/wasm.rs b/rust/pubky/pubky/src/wasm.rs deleted file mode 100644 index cbbf71b..0000000 --- a/rust/pubky/pubky/src/wasm.rs +++ /dev/null @@ -1,250 +0,0 @@ -use std::{ - collections::HashSet, - sync::{Arc, RwLock}, -}; - -use js_sys::{Array, Uint8Array}; -use wasm_bindgen::prelude::*; - -use url::Url; - -use pubky_common::capabilities::Capabilities; - -use crate::error::Error; -use crate::PubkyClient; - -mod http; -mod keys; -mod pkarr; -mod recovery_file; -mod session; - -use keys::{Keypair, PublicKey}; -use session::Session; - -impl Default for PubkyClient { - fn default() -> Self { - Self::new() - } -} - -static DEFAULT_RELAYS: [&str; 1] = ["https://relay.pkarr.org"]; -static TESTNET_RELAYS: [&str; 1] = ["http://localhost:15411/pkarr"]; - -#[wasm_bindgen] -impl PubkyClient { - #[wasm_bindgen(constructor)] - pub fn new() -> Self { - Self { - http: reqwest::Client::builder().build().unwrap(), - session_cookies: Arc::new(RwLock::new(HashSet::new())), - pkarr_relays: DEFAULT_RELAYS.into_iter().map(|s| s.to_string()).collect(), - } - } - - /// Create a client with with configurations appropriate for local testing: - /// - set Pkarr relays to `["http://localhost:15411/pkarr"]` instead of default relay. - #[wasm_bindgen] - pub fn testnet() -> Self { - Self { - http: reqwest::Client::builder().build().unwrap(), - session_cookies: Arc::new(RwLock::new(HashSet::new())), - pkarr_relays: TESTNET_RELAYS.into_iter().map(|s| s.to_string()).collect(), - } - } - - /// Set Pkarr relays used for publishing and resolving Pkarr packets. - /// - /// By default, [PubkyClient] will use `["https://relay.pkarr.org"]` - #[wasm_bindgen(js_name = "setPkarrRelays")] - pub fn set_pkarr_relays(mut self, relays: Vec) -> Self { - self.pkarr_relays = relays; - self - } - - // Read the set of pkarr relays used by this client. - #[wasm_bindgen(js_name = "getPkarrRelays")] - pub fn get_pkarr_relays(&self) -> Vec { - self.pkarr_relays.clone() - } - - /// Signup to a homeserver and update Pkarr accordingly. - /// - /// The homeserver is a Pkarr domain name, where the TLD is a Pkarr public key - /// for example "pubky.o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy" - #[wasm_bindgen] - pub async fn signup( - &self, - keypair: &Keypair, - homeserver: &PublicKey, - ) -> Result { - Ok(Session( - self.inner_signup(keypair.as_inner(), homeserver.as_inner()) - .await - .map_err(JsValue::from)?, - )) - } - - /// Check the current sesison for a given Pubky in its homeserver. - /// - /// Returns [Session] or `None` (if recieved `404 NOT_FOUND`), - /// or throws the recieved error if the response has any other `>=400` status code. - #[wasm_bindgen] - pub async fn session(&self, pubky: &PublicKey) -> Result, JsValue> { - self.inner_session(pubky.as_inner()) - .await - .map(|s| s.map(Session)) - .map_err(|e| e.into()) - } - - /// Signout from a homeserver. - #[wasm_bindgen] - pub async fn signout(&self, pubky: &PublicKey) -> Result<(), JsValue> { - self.inner_signout(pubky.as_inner()) - .await - .map_err(|e| e.into()) - } - - /// Signin to a homeserver using the root Keypair. - #[wasm_bindgen] - pub async fn signin(&self, keypair: &Keypair) -> Result<(), JsValue> { - self.inner_signin(keypair.as_inner()) - .await - .map(|_| ()) - .map_err(|e| e.into()) - } - - /// Return `pubkyauth://` url and wait for the incoming [AuthToken] - /// verifying that AuthToken, and if capabilities were requested, signing in to - /// the Pubky's homeserver and returning the [Session] information. - /// - /// Returns a tuple of [pubkyAuthUrl, Promise] - #[wasm_bindgen(js_name = "authRequest")] - pub fn auth_request(&self, relay: &str, capabilities: &str) -> Result { - let mut relay: Url = relay - .try_into() - .map_err(|_| Error::Generic("Invalid relay Url".into()))?; - - let (pubkyauth_url, client_secret) = self.create_auth_request( - &mut relay, - &Capabilities::try_from(capabilities).map_err(|_| "Invalid capaiblities")?, - )?; - - let this = self.clone(); - - let future = async move { - this.subscribe_to_auth_response(relay, &client_secret) - .await - .map(|pubky| JsValue::from(PublicKey(pubky))) - .map_err(|err| JsValue::from_str(&format!("{:?}", err))) - }; - - let promise = wasm_bindgen_futures::future_to_promise(future); - - // Return the URL and the promise - let js_tuple = js_sys::Array::new(); - js_tuple.push(&JsValue::from_str(pubkyauth_url.as_ref())); - js_tuple.push(&promise); - - Ok(js_tuple) - } - - /// Sign an [pubky_common::auth::AuthToken], encrypt it and send it to the - /// source of the pubkyauth request url. - #[wasm_bindgen(js_name = "sendAuthToken")] - pub async fn send_auth_token( - &self, - keypair: &Keypair, - pubkyauth_url: &str, - ) -> Result<(), JsValue> { - let pubkyauth_url: Url = pubkyauth_url - .try_into() - .map_err(|_| Error::Generic("Invalid relay Url".into()))?; - - self.inner_send_auth_token(keypair.as_inner(), pubkyauth_url) - .await?; - - Ok(()) - } - - // === Public data === - - #[wasm_bindgen] - /// Upload a small payload to a given path. - pub async fn put(&self, url: &str, content: &[u8]) -> Result<(), JsValue> { - self.inner_put(url, content).await.map_err(|e| e.into()) - } - - /// Download a small payload from a given path relative to a pubky author. - #[wasm_bindgen] - pub async fn get(&self, url: &str) -> Result, JsValue> { - self.inner_get(url) - .await - .map(|b| b.map(|b| (&*b).into())) - .map_err(|e| e.into()) - } - - /// Delete a file at a path relative to a pubky author. - #[wasm_bindgen] - pub async fn delete(&self, url: &str) -> Result<(), JsValue> { - self.inner_delete(url).await.map_err(|e| e.into()) - } - - /// Returns a list of Pubky urls (as strings). - /// - /// - `url`: The Pubky url (string) to the directory you want to list its content. - /// - `cursor`: Either a full `pubky://` Url (from previous list response), - /// or a path (to a file or directory) relative to the `url` - /// - `reverse`: List in reverse order - /// - `limit` Limit the number of urls in the response - /// - `shallow`: List directories and files, instead of flat list of files. - #[wasm_bindgen] - pub async fn list( - &self, - url: &str, - cursor: Option, - reverse: Option, - limit: Option, - shallow: Option, - ) -> Result { - // TODO: try later to return Vec from async function. - - if let Some(cursor) = cursor { - return self - .inner_list(url)? - .reverse(reverse.unwrap_or(false)) - .limit(limit.unwrap_or(u16::MAX)) - .cursor(&cursor) - .shallow(shallow.unwrap_or(false)) - .send() - .await - .map(|urls| { - let js_array = Array::new(); - - for url in urls { - js_array.push(&JsValue::from_str(&url)); - } - - js_array - }) - .map_err(|e| e.into()); - } - - self.inner_list(url)? - .reverse(reverse.unwrap_or(false)) - .limit(limit.unwrap_or(u16::MAX)) - .shallow(shallow.unwrap_or(false)) - .send() - .await - .map(|urls| { - let js_array = Array::new(); - - for url in urls { - js_array.push(&JsValue::from_str(&url)); - } - - js_array - }) - .map_err(|e| e.into()) - } -} diff --git a/rust/pubky/pubky/src/wasm/http.rs b/rust/pubky/pubky/src/wasm/http.rs deleted file mode 100644 index 61fee29..0000000 --- a/rust/pubky/pubky/src/wasm/http.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::PubkyClient; - -use reqwest::{Method, RequestBuilder, Response}; -use url::Url; - -impl PubkyClient { - pub(crate) fn request(&self, method: Method, url: Url) -> RequestBuilder { - let mut request = self.http.request(method, url).fetch_credentials_include(); - - for cookie in self.session_cookies.read().unwrap().iter() { - request = request.header("Cookie", cookie); - } - - request - } - - // Support cookies for nodejs - - pub(crate) fn store_session(&self, response: &Response) { - if let Some(cookie) = response - .headers() - .get("set-cookie") - .and_then(|h| h.to_str().ok()) - .and_then(|s| s.split(';').next()) - { - self.session_cookies - .write() - .unwrap() - .insert(cookie.to_string()); - } - } - pub(crate) fn remove_session(&self, pubky: &pkarr::PublicKey) { - let key = pubky.to_string(); - - self.session_cookies - .write() - .unwrap() - .retain(|cookie| !cookie.starts_with(&key)); - } -} diff --git a/rust/pubky/pubky/src/wasm/keys.rs b/rust/pubky/pubky/src/wasm/keys.rs deleted file mode 100644 index 3b27045..0000000 --- a/rust/pubky/pubky/src/wasm/keys.rs +++ /dev/null @@ -1,99 +0,0 @@ -use wasm_bindgen::prelude::*; - -use crate::Error; - -#[wasm_bindgen] -pub struct Keypair(pkarr::Keypair); - -#[wasm_bindgen] -impl Keypair { - #[wasm_bindgen] - /// Generate a random [Keypair] - pub fn random() -> Self { - Self(pkarr::Keypair::random()) - } - - /// Generate a [Keypair] from a secret key. - #[wasm_bindgen(js_name = "fromSecretKey")] - pub fn from_secret_key(secret_key: js_sys::Uint8Array) -> Result { - if !js_sys::Uint8Array::instanceof(&secret_key) { - return Err("Expected secret_key to be an instance of Uint8Array".into()); - } - - let len = secret_key.byte_length(); - if len != 32 { - return Err(format!("Expected secret_key to be 32 bytes, got {len}"))?; - } - - let mut bytes = [0; 32]; - secret_key.copy_to(&mut bytes); - - Ok(Self(pkarr::Keypair::from_secret_key(&bytes))) - } - - /// Returns the secret key of this keypair. - #[wasm_bindgen(js_name = "secretKey")] - pub fn secret_key(&self) -> js_sys::Uint8Array { - self.0.secret_key().as_slice().into() - } - - /// Returns the [PublicKey] of this keypair. - #[wasm_bindgen(js_name = "publicKey")] - pub fn public_key(&self) -> PublicKey { - PublicKey(self.0.public_key()) - } -} - -impl Keypair { - pub fn as_inner(&self) -> &pkarr::Keypair { - &self.0 - } -} - -impl From for Keypair { - fn from(keypair: pkarr::Keypair) -> Self { - Self(keypair) - } -} - -#[wasm_bindgen] -pub struct PublicKey(pub(crate) pkarr::PublicKey); - -#[wasm_bindgen] -impl PublicKey { - #[wasm_bindgen] - /// Convert the PublicKey to Uint8Array - pub fn to_uint8array(&self) -> js_sys::Uint8Array { - js_sys::Uint8Array::from(self.0.as_bytes().as_slice()) - } - - #[wasm_bindgen] - /// Returns the z-base32 encoding of this public key - pub fn z32(&self) -> String { - self.0.to_string() - } - - #[wasm_bindgen(js_name = "from")] - /// @throws - pub fn try_from(value: JsValue) -> Result { - let string = value - .as_string() - .ok_or("Couldn't create a PublicKey from this type of value")?; - - Ok(PublicKey( - pkarr::PublicKey::try_from(string).map_err(Error::Pkarr)?, - )) - } -} - -impl PublicKey { - pub fn as_inner(&self) -> &pkarr::PublicKey { - &self.0 - } -} - -impl From for PublicKey { - fn from(value: pkarr::PublicKey) -> Self { - PublicKey(value) - } -} diff --git a/rust/pubky/pubky/src/wasm/pkarr.rs b/rust/pubky/pubky/src/wasm/pkarr.rs deleted file mode 100644 index 49726f6..0000000 --- a/rust/pubky/pubky/src/wasm/pkarr.rs +++ /dev/null @@ -1,48 +0,0 @@ -use reqwest::StatusCode; - -pub use pkarr::{PublicKey, SignedPacket}; - -use crate::error::Result; -use crate::PubkyClient; - -// TODO: Add an in memory cache of packets - -impl PubkyClient { - //TODO: migrate to pkarr::PkarrRelayClient - pub(crate) async fn pkarr_resolve( - &self, - public_key: &PublicKey, - ) -> Result> { - //TODO: Allow multiple relays in parallel - let relay = self.pkarr_relays.first().expect("initialized with relays"); - - let res = self - .http - .get(format!("{relay}/{}", public_key)) - .send() - .await?; - - if res.status() == StatusCode::NOT_FOUND { - return Ok(None); - }; - - // TODO: guard against too large responses. - let bytes = res.bytes().await?; - - let existing = SignedPacket::from_relay_payload(public_key, &bytes)?; - - Ok(Some(existing)) - } - - pub(crate) async fn pkarr_publish(&self, signed_packet: &SignedPacket) -> Result<()> { - let relay = self.pkarr_relays.first().expect("initialized with relays"); - - self.http - .put(format!("{relay}/{}", signed_packet.public_key())) - .body(signed_packet.to_relay_payload()) - .send() - .await?; - - Ok(()) - } -} diff --git a/rust/pubky/pubky/src/wasm/recovery_file.rs b/rust/pubky/pubky/src/wasm/recovery_file.rs deleted file mode 100644 index 7b85178..0000000 --- a/rust/pubky/pubky/src/wasm/recovery_file.rs +++ /dev/null @@ -1,24 +0,0 @@ -use js_sys::Uint8Array; -use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; - -use crate::error::Error; - -use super::keys::Keypair; - -/// Create a recovery file of the `keypair`, containing the secret key encrypted -/// using the `passphrase`. -#[wasm_bindgen(js_name = "createRecoveryFile")] -pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result { - pubky_common::recovery_file::create_recovery_file(keypair.as_inner(), passphrase) - .map(|b| b.as_slice().into()) - .map_err(|e| Error::from(e).into()) -} - -/// Create a recovery file of the `keypair`, containing the secret key encrypted -/// using the `passphrase`. -#[wasm_bindgen(js_name = "decryptRecoveryFile")] -pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result { - pubky_common::recovery_file::decrypt_recovery_file(recovery_file, passphrase) - .map(Keypair::from) - .map_err(|e| Error::from(e).into()) -} diff --git a/rust/pubky/pubky/src/wasm/session.rs b/rust/pubky/pubky/src/wasm/session.rs deleted file mode 100644 index e838a80..0000000 --- a/rust/pubky/pubky/src/wasm/session.rs +++ /dev/null @@ -1,27 +0,0 @@ -use pubky_common::session; - -use wasm_bindgen::prelude::*; - -use super::keys::PublicKey; - -#[wasm_bindgen] -pub struct Session(pub(crate) session::Session); - -#[wasm_bindgen] -impl Session { - /// Return the [PublicKey] of this session - #[wasm_bindgen] - pub fn pubky(&self) -> PublicKey { - self.0.pubky().clone().into() - } - - /// Return the capabilities that this session has. - #[wasm_bindgen] - pub fn capabilities(&self) -> Vec { - self.0 - .capabilities() - .iter() - .map(|c| c.to_string()) - .collect() - } -} diff --git a/rust/src/auth.rs b/rust/src/auth.rs deleted file mode 100644 index 0d27dc2..0000000 --- a/rust/src/auth.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::keypair::get_keypair_from_secret_key; -use crate::{PubkyAuthDetails, Capability}; -use crate::utils::create_response_vector; -use std::collections::HashMap; -use pubky::PubkyClient; -use serde_json; -use url::Url; - -pub async fn authorize(url: String, secret_key: String) -> Vec { - let client = PubkyClient::testnet(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - let parsed_url = match Url::parse(&url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - - match client.send_auth_token(&keypair, parsed_url).await { - Ok(_) => create_response_vector(false, "send_auth_token success".to_string()), - Err(error) => create_response_vector(true, format!("send_auth_token failure: {}", error)), - } -} - -pub fn pubky_auth_details_to_json(details: &PubkyAuthDetails) -> Result { - serde_json::to_string(details).map_err(|_| "Error serializing to JSON".to_string()) -} - -pub fn parse_pubky_auth_url(url_str: &str) -> Result { - let url = Url::parse(url_str).map_err(|_| "Invalid URL".to_string())?; - - if url.scheme() != "pubkyauth" { - return Err("Invalid scheme, expected 'pubkyauth'".to_string()); - } - - // Collect query pairs into a HashMap for efficient access - let query_params: HashMap<_, _> = url.query_pairs().into_owned().collect(); - - let relay = query_params - .get("relay") - .cloned() - .ok_or_else(|| "Missing relay".to_string())?; - - let capabilities_str = query_params - .get("capabilities") - .or_else(|| query_params.get("caps")) - .cloned() - .ok_or_else(|| "Missing capabilities".to_string())?; - - let secret = query_params - .get("secret") - .cloned() - .ok_or_else(|| "Missing secret".to_string())?; - - // Parse capabilities - let capabilities = capabilities_str - .split(',') - .map(|capability| { - let mut parts = capability.splitn(2, ':'); - let path = parts - .next() - .ok_or_else(|| format!("Invalid capability format in '{}'", capability))?; - let permission = parts - .next() - .ok_or_else(|| format!("Invalid capability format in '{}'", capability))?; - Ok(Capability { - path: path.to_string(), - permission: permission.to_string(), - }) - }) - .collect::, String>>()?; - - Ok(PubkyAuthDetails { - relay, - capabilities, - secret, - }) -} diff --git a/rust/src/bin/uniffi-bindgen.rs b/rust/src/bin/uniffi-bindgen.rs deleted file mode 100644 index f6cff6c..0000000 --- a/rust/src/bin/uniffi-bindgen.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - uniffi::uniffi_bindgen_main() -} diff --git a/rust/src/keypair.rs b/rust/src/keypair.rs deleted file mode 100644 index 80db9c2..0000000 --- a/rust/src/keypair.rs +++ /dev/null @@ -1,34 +0,0 @@ -use pkarr::Keypair; - -/** - * Get a keypair from a secret key - */ -pub fn get_keypair_from_secret_key(secret_key: &str) -> Result { - let bytes = match hex::decode(&secret_key) { - Ok(bytes) => bytes, - Err(_) => return Err("Failed to decode secret key".to_string()) - }; - - let secret_key_bytes: [u8; 32] = match bytes.try_into() { - Ok(secret_key) => secret_key, - Err(_) => { - return Err("Failed to convert secret key to 32-byte array".to_string()); - } - }; - - Ok(Keypair::from_secret_key(&secret_key_bytes)) -} - -/** - * Get the secret key from a keypair - */ -pub fn get_secret_key_from_keypair(keypair: &Keypair) -> String { - hex::encode(keypair.secret_key()) -} - -/** - * Generate a new keypair - */ -pub fn generate_keypair() -> Keypair { - Keypair::random() -} \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs deleted file mode 100644 index 310bb02..0000000 --- a/rust/src/lib.rs +++ /dev/null @@ -1,629 +0,0 @@ -mod types; -mod keypair; -mod auth; -mod utils; - -pub use types::*; -pub use keypair::*; -pub use auth::*; -pub use utils::*; - -uniffi::setup_scaffolding!(); - -use std::str; -use std::collections::HashMap; -use base64::Engine; -use base64::engine::general_purpose; -use pubky::PubkyClient; -use hex; -use hex::ToHex; -use serde::Serialize; -use url::Url; -use tokio; -use pkarr::{PkarrClient, SignedPacket, Keypair, dns, PublicKey}; -use pkarr::dns::rdata::{RData, HTTPS, SVCB}; -use pkarr::dns::{Packet, ResourceRecord}; -use serde_json::json; -use utils::*; -use once_cell::sync::Lazy; -use std::sync::{Arc, Mutex}; -use std::time::Duration; -use pkarr::bytes::Bytes; -use pubky_common::session::Session; -use tokio::runtime::Runtime; -use tokio::time; - -static PUBKY_CLIENT: Lazy> = Lazy::new(|| { - Arc::new(PubkyClient::testnet()) -}); - -static TOKIO_RUNTIME: Lazy> = Lazy::new(|| { - Arc::new( - Runtime::new().expect("Failed to create Tokio runtime") - ) -}); - -// Define the EventListener trait -#[uniffi::export(callback_interface)] -pub trait EventListener: Send + Sync { - fn on_event_occurred(&self, event_data: String); -} - -#[derive(uniffi::Object)] -pub struct EventNotifier { - listener: Arc>>>, -} - -impl EventNotifier { - #[uniffi::constructor] - pub fn new() -> Self { - Self { - listener: Arc::new(Mutex::new(None)), - } - } - - pub fn set_listener(&self, listener: Box) { - let mut lock = self.listener.lock().unwrap(); - *lock = Some(listener); - } - - pub fn remove_listener(&self) { - let mut lock = self.listener.lock().unwrap(); - *lock = None; - } - - pub fn notify_event(&self, event_data: String) { - let lock = self.listener.lock().unwrap(); - if let Some(listener) = &*lock { - listener.on_event_occurred(event_data); - } - } -} - -static EVENT_NOTIFIER: Lazy> = Lazy::new(|| { - Arc::new(EventNotifier::new()) -}); - -#[uniffi::export] -pub fn set_event_listener(listener: Box) { - EVENT_NOTIFIER.as_ref().set_listener(listener); -} - -#[uniffi::export] -pub fn remove_event_listener() { - EVENT_NOTIFIER.as_ref().remove_listener(); -} - -pub fn start_internal_event_loop() { - let event_notifier = EVENT_NOTIFIER.clone(); - let runtime = TOKIO_RUNTIME.clone(); - runtime.spawn(async move { - let mut interval = time::interval(Duration::from_secs(2)); - loop { - interval.tick().await; - event_notifier.as_ref().notify_event("Internal event triggered".to_string()); - } - }); -} - -#[uniffi::export] -pub fn delete_file(url: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let parsed_url = match Url::parse(&url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - match client.delete(parsed_url).await { - Ok(_) => create_response_vector(false, "Deleted successfully".to_string()), - Err(error) => create_response_vector(true, format!("Failed to delete: {}", error)), - } - }) -} - -#[uniffi::export] -pub fn session(pubky: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let public_key = match PublicKey::try_from(pubky) { - Ok(key) => key, - Err(error) => return create_response_vector(true, format!("Invalid homeserver public key: {}", error)), - }; - let result = match client.session(&public_key).await { - Ok(session) => session, - Err(error) => return create_response_vector(true, format!("Failed to get session: {}", error)), - }; - let session: Session = match result { - Some(session) => session, - None => return create_response_vector(true, "No session returned".to_string()), - }; - - let json_obj = json!({ - "pubky": session.pubky().to_string(), - "capabilities": session.capabilities().iter().map(|c| c.to_string()).collect::>(), - }); - - let json_str = match serde_json::to_string(&json_obj) { - Ok(json) => json, - Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)), - }; - - create_response_vector(false, json_str) - }) -} - -#[uniffi::export] -pub fn generate_secret_key() -> Vec { - let keypair = generate_keypair(); - let secret_key = get_secret_key_from_keypair(&keypair); - let public_key = keypair.public_key(); - let uri = public_key.to_uri_string(); - let json_obj = json!({ - "secret_key": secret_key, - "public_key": public_key.to_string(), - "uri": uri, - }); - - let json_str = match serde_json::to_string(&json_obj) { - Ok(json) => json, - Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)), - }; - start_internal_event_loop(); - create_response_vector(false, json_str) -} - -#[uniffi::export] -pub fn get_public_key_from_secret_key(secret_key: String) -> Vec { - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - let public_key = keypair.public_key(); - let uri = public_key.to_uri_string(); - let json_obj = json!({ - "public_key": public_key.to_string(), - "uri": uri, - }); - - let json_str = match serde_json::to_string(&json_obj) { - Ok(json) => json, - Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)), - }; - create_response_vector(false, json_str) -} - -#[uniffi::export] -pub fn publish_https(record_name: String, target: String, secret_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - // Create SVCB record with the target domain - let target = match target.as_str().try_into() { - Ok(target) => target, - Err(e) => return create_response_vector(true, format!("Invalid target: {}", e)), - }; - let svcb = SVCB::new(0, target); - - // Create HTTPS record - let https_record = HTTPS(svcb); - - // Create DNS packet - let mut packet = Packet::new_reply(0); - let dns_name = match dns::Name::new(&record_name) { - Ok(name) => name, - Err(e) => return create_response_vector(true, format!("Invalid DNS name: {}", e)), - }; - - packet.answers.push(ResourceRecord::new( - dns_name, - dns::CLASS::IN, - 3600, // TTL in seconds - dns::rdata::RData::HTTPS(https_record), - )); - - let signed_packet = match SignedPacket::from_packet(&keypair, &packet) { - Ok(signed_packet) => signed_packet, - Err(e) => return create_response_vector(true, format!("Failed to create signed packet: {}", e)), - }; - - match client.pkarr().publish(&signed_packet).await { - Ok(()) => create_response_vector(false, keypair.public_key().to_string()), - Err(e) => create_response_vector(true, format!("Failed to publish: {}", e)), - } - }) -} - -#[uniffi::export] -pub fn resolve_https(public_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let public_key = match public_key.as_str().try_into() { - Ok(key) => key, - Err(e) => return create_response_vector(true, format!("Invalid public key: {}", e)), - }; - - let client = PUBKY_CLIENT.clone(); - - match client.pkarr().resolve(&public_key).await { - Ok(Some(signed_packet)) => { - // Extract HTTPS records from the signed packet - let https_records: Vec = signed_packet.packet().answers.iter() - .filter_map(|record| { - if let dns::rdata::RData::HTTPS(https) = &record.rdata { - // Create a JSON object - let mut https_json = serde_json::json!({ - "name": record.name.to_string(), - "class": format!("{:?}", record.class), - "ttl": record.ttl, - "priority": https.0.priority, - "target": https.0.target.to_string(), - }); - - // Access specific parameters using the constants from SVCB - if let Some(port_param) = https.0.get_param(SVCB::PORT) { - if port_param.len() == 2 { - let port = u16::from_be_bytes([port_param[0], port_param[1]]); - https_json["port"] = serde_json::json!(port); - } - } - - // Access ALPN parameter if needed - if let Some(alpn_param) = https.0.get_param(SVCB::ALPN) { - // Parse ALPN protocols (list of character strings) - let mut position = 0; - let mut alpn_protocols = Vec::new(); - while position < alpn_param.len() { - let length = alpn_param[position] as usize; - position += 1; - if position + length <= alpn_param.len() { - let protocol = String::from_utf8_lossy( - &alpn_param[position..position + length], - ); - alpn_protocols.push(protocol.to_string()); - position += length; - } else { - break; // Malformed ALPN parameter - } - } - https_json["alpn"] = serde_json::json!(alpn_protocols); - } - // TODO: Add other parameters as needed. - Some(https_json) - } else { - None - } - }) - .collect(); - - if https_records.is_empty() { - return create_response_vector(true, "No HTTPS records found".to_string()); - } - - // Create JSON response - let json_obj = json!({ - "public_key": public_key.to_string(), - "https_records": https_records, - "last_seen": signed_packet.last_seen(), - "timestamp": signed_packet.timestamp(), - }); - - let json_str = match serde_json::to_string(&json_obj) { - Ok(json) => json, - Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)), - }; - - create_response_vector(false, json_str) - }, - Ok(None) => create_response_vector(true, "No signed packet found".to_string()), - Err(e) => create_response_vector(true, format!("Failed to resolve: {}", e)), - } - }) -} - -#[uniffi::export] -pub fn sign_up(secret_key: String, homeserver: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - let homeserver_public_key = match PublicKey::try_from(homeserver) { - Ok(key) => key, - Err(error) => return create_response_vector(true, format!("Invalid homeserver public key: {}", error)), - }; - - match client.signup(&keypair, &homeserver_public_key).await { - Ok(session) => create_response_vector(false, session.pubky().to_string()), - Err(error) => create_response_vector(true, format!("signup failure: {}", error)), - } - }) -} - -#[uniffi::export] -pub fn sign_in(secret_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - match client.signin(&keypair).await { - Ok(_) => create_response_vector(false, "Sign in success".to_string()), - Err(error) => { - create_response_vector(true, format!("Failed to sign in: {}", error)) - } - } - }) -} - -#[uniffi::export] -pub fn sign_out(secret_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - match client.signout(&keypair.public_key()).await { - Ok(_) => create_response_vector(false, "Sign out success".to_string()), - Err(error) => { - create_response_vector(true, format!("Failed to sign out: {}", error)) - } - } - }) -} - -#[uniffi::export] -pub fn put(url: String, content: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - match client.put(parsed_url, &content.as_bytes()).await { - Ok(_) => create_response_vector(false, trimmed_url.to_string()), - Err(error) => { - create_response_vector(true, format!("Failed to put: {}", error)) - } - } - }) -} - -#[uniffi::export] -pub fn get(url: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - let result: Option = match client.get(parsed_url).await { - Ok(res) => res, - Err(_) => return create_response_vector(true, "Request failed".to_string()), - }; - let bytes = match result { - Some(bytes) => bytes, - None => return create_response_vector(true, "No data returned".to_string()), - }; - let string = match str::from_utf8(&bytes) { - Ok(s) => s.to_string(), - Err(_) => return create_response_vector(true, "Invalid UTF-8 sequence".to_string()), - }; - create_response_vector(false, string) - }) -} - -/** -* Resolve a signed packet from a public key -* @param public_key The public key to resolve -* @returns A vector with two elements: the first element is a boolean indicating success or failure, -* and the second element is the response data (either an error message or the resolved signed packet) -**/ -#[uniffi::export] -pub fn resolve(public_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let public_key = match public_key.as_str().try_into() { - Ok(key) => key, - Err(e) => return create_response_vector(true, format!("Invalid zbase32 encoded key: {}", e)), - }; - let client = PUBKY_CLIENT.clone(); - - match client.pkarr().resolve(&public_key).await { - Ok(Some(signed_packet)) => { - // Collect references to ResourceRecords from the signed packet's answers - let all_records: Vec<&ResourceRecord> = signed_packet.packet().answers.iter().collect(); - // Convert each ResourceRecord to a JSON value, handling errors appropriately - let json_records: Vec = all_records - .iter() - .filter_map(|record| { - match resource_record_to_json(record) { - Ok(json_value) => Some(json_value), - Err(e) => { - eprintln!("Error converting record to JSON: {}", e); - None - } - } - }) - .collect(); - - let bytes = signed_packet.as_bytes(); - let public_key = &bytes[..32]; - let signature = &bytes[32..96]; - let timestamp = signed_packet.timestamp(); - let dns_packet = &bytes[104..]; - let hex: String = signed_packet.encode_hex(); - - let json_obj = json!({ - "signed_packet": hex, - "public_key": general_purpose::STANDARD.encode(public_key), - "signature": general_purpose::STANDARD.encode(signature), - "timestamp": timestamp, - "last_seen": signed_packet.last_seen(), - "dns_packet": general_purpose::STANDARD.encode(dns_packet), - "records": json_records - }); - - let json_str = serde_json::to_string(&json_obj) - .expect("Failed to convert JSON object to string"); - - create_response_vector(false, json_str) - }, - Ok(None) => { - create_response_vector(true, "No signed packet found".to_string()) - } - Err(e) => { - create_response_vector(true, format!("Failed to resolve: {}", e)) - } - } - }) -} - -#[uniffi::export] -pub fn publish(record_name: String, record_content: String, secret_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - let mut packet = dns::Packet::new_reply(0); - - let dns_name = match dns::Name::new(&record_name) { - Ok(name) => name, - Err(e) => return create_response_vector(true, format!("Failed to create DNS name: {}", e)), - }; - - let record_content_str: &str = record_content.as_str(); - - let txt_record = match record_content_str.try_into() { - Ok(value) => RData::TXT(value), - Err(e) => { - return create_response_vector(true, format!("Failed to convert string to TXT record: {}", e)) - } - }; - - packet.answers.push(dns::ResourceRecord::new( - dns_name, - dns::CLASS::IN, - 30, - txt_record, - )); - - match SignedPacket::from_packet(&keypair, &packet) { - Ok(signed_packet) => { - match client.pkarr().publish(&signed_packet).await { - Ok(()) => { - create_response_vector(false, keypair.public_key().to_string()) - } - Err(e) => { - create_response_vector(true, format!("Failed to publish: {}", e)) - } - } - } - Err(e) => { - create_response_vector(true, format!("Failed to create signed packet: {}", e)) - } - } - }) -} -#[uniffi::export] -pub fn list(url: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(async { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - let list_builder = match client.list(parsed_url) { - Ok(list) => list, - Err(error) => return create_response_vector(true, format!("Failed to list: {}", error)), - }; - // Execute the non-Send part synchronously - let send_future = list_builder.send(); - let send_res = match send_future.await { - Ok(res) => res, - Err(error) => return create_response_vector(true, format!("Failed to send list request: {}", error)) - }; - let json_string = match serde_json::to_string(&send_res) { - Ok(json) => json, - Err(error) => return create_response_vector(true, format!("Failed to serialize JSON: {}", error)), - }; - create_response_vector(false, json_string) - }) -} - -#[uniffi::export] -pub fn auth(url: String, secret_key: String) -> Vec { - let runtime = TOKIO_RUNTIME.clone(); - runtime.block_on(authorize(url, secret_key)) -} - -#[uniffi::export] -pub fn parse_auth_url(url: String) -> Vec { - let parsed_details = match parse_pubky_auth_url(&url) { - Ok(details) => details, - Err(error) => return create_response_vector(true, error), - }; - match pubky_auth_details_to_json(&parsed_details) { - Ok(json) => create_response_vector(false, json), - Err(error) => create_response_vector(true, error), - } -} - -#[uniffi::export] -pub fn create_recovery_file(secret_key: String, passphrase: String,) -> Vec { - if secret_key.is_empty() || passphrase.is_empty() { - return create_response_vector(true, "Secret key and passphrase must not be empty".to_string()); - } - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - let recovery_file_bytes = match PubkyClient::create_recovery_file(&keypair, &passphrase) { - Ok(bytes) => bytes, - Err(_) => return create_response_vector(true, "Failed to create recovery file".to_string()), - }; - let recovery_file = base64::encode(&recovery_file_bytes); - create_response_vector(false, recovery_file) -} - -#[uniffi::export] -pub fn decrypt_recovery_file(recovery_file: String, passphrase: String) -> Vec { - if recovery_file.is_empty() || passphrase.is_empty() { - return create_response_vector(true, "Recovery file and passphrase must not be empty".to_string()); - } - let recovery_file_bytes = match base64::decode(&recovery_file) { - Ok(bytes) => bytes, - Err(error) => return create_response_vector(true, format!("Failed to decode recovery file: {}", error)), - }; - let keypair = match PubkyClient::decrypt_recovery_file(&recovery_file_bytes, &passphrase) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, "Failed to decrypt recovery file".to_string()), - }; - let secret_key = get_secret_key_from_keypair(&keypair); - create_response_vector(false, secret_key) -} diff --git a/rust/src/types.rs b/rust/src/types.rs deleted file mode 100644 index 56f9b20..0000000 --- a/rust/src/types.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::Serialize; - -#[derive(Debug, Serialize)] -pub struct Capability { - pub path: String, - pub permission: String, -} - -#[derive(Debug, Serialize)] -pub struct PubkyAuthDetails { - pub relay: String, - pub capabilities: Vec, - pub secret: String, -} \ No newline at end of file diff --git a/rust/src/utils.rs b/rust/src/utils.rs deleted file mode 100644 index 58833f7..0000000 --- a/rust/src/utils.rs +++ /dev/null @@ -1,244 +0,0 @@ -use std::error::Error; -use std::net::{Ipv4Addr, Ipv6Addr}; -use serde_json::json; -use base64::{engine::general_purpose, Engine}; -use pkarr::dns::rdata::RData; -use pkarr::dns::ResourceRecord; - -pub fn create_response_vector(error: bool, data: String) -> Vec { - if error { - vec!["error".to_string(), data] - } else { - vec!["success".to_string(), data] - } -} - -pub fn extract_rdata_for_json(record: &ResourceRecord) -> serde_json::Value { - match &record.rdata { - RData::TXT(txt) => { - let attributes = txt.attributes(); - let strings: Vec = attributes.into_iter() - .map(|(key, value)| { - match value { - Some(v) => format!("{}={}", key, v), - None => key, - } - }) - .collect(); - json!({ - "type": "TXT", - "strings": strings - }) - }, - RData::A(a) => { - let ipv4 = Ipv4Addr::from(a.address); - json!({ - "type": "A", - "address": ipv4.to_string() - }) - }, - RData::AAAA(aaaa) => { - let ipv6 = Ipv6Addr::from(aaaa.address); - json!({ - "type": "AAAA", - "address": ipv6.to_string() - }) - }, - RData::AFSDB(afsdb) => { - json!({ - "type": "AFSDB", - "subtype": afsdb.subtype, - "hostname": afsdb.hostname.to_string() - }) - }, - RData::CAA(caa) => { - json!({ - "type": "CAA", - "flag": caa.flag, - "tag": caa.tag.to_string(), - "value": caa.value.to_string() - }) - }, - RData::HINFO(hinfo) => { - json!({ - "type": "HINFO", - "cpu": hinfo.cpu.to_string(), - "os": hinfo.os.to_string() - }) - }, - RData::ISDN(isdn) => { - json!({ - "type": "ISDN", - "address": isdn.address.to_string(), - "sa": isdn.sa.to_string() - }) - }, - RData::LOC(loc) => { - json!({ - "type": "LOC", - "version": loc.version, - "size": loc.size, - "horizontal_precision": loc.horizontal_precision, - "vertical_precision": loc.vertical_precision, - "latitude": loc.latitude, - "longitude": loc.longitude, - "altitude": loc.altitude - }) - }, - RData::MINFO(minfo) => { - json!({ - "type": "MINFO", - "rmailbox": minfo.rmailbox.to_string(), - "emailbox": minfo.emailbox.to_string() - }) - }, - RData::MX(mx) => { - json!({ - "type": "MX", - "preference": mx.preference, - "exchange": mx.exchange.to_string() - }) - }, - RData::NAPTR(naptr) => { - json!({ - "type": "NAPTR", - "order": naptr.order, - "preference": naptr.preference, - "flags": naptr.flags.to_string(), - "services": naptr.services.to_string(), - "regexp": naptr.regexp.to_string(), - "replacement": naptr.replacement.to_string() - }) - }, - RData::NULL(_, null_record) => { - json!({ - "type": "NULL", - "data": base64::encode(null_record.get_data()) - }) - }, - RData::OPT(opt) => { - json!({ - "type": "OPT", - "udp_packet_size": opt.udp_packet_size, - "version": opt.version, - "opt_codes": opt.opt_codes.iter().map(|code| { - json!({ - "code": code.code, - "data": base64::encode(&code.data) - }) - }).collect::>() - }) - }, - RData::RouteThrough(rt) => { - json!({ - "type": "RT", - "preference": rt.preference, - "intermediate_host": rt.intermediate_host.to_string() - }) - }, - RData::RP(rp) => { - json!({ - "type": "RP", - "mbox": rp.mbox.to_string(), - "txt": rp.txt.to_string() - }) - }, - RData::SOA(soa) => { - json!({ - "type": "SOA", - "mname": soa.mname.to_string(), - "rname": soa.rname.to_string(), - "serial": soa.serial, - "refresh": soa.refresh, - "retry": soa.retry, - "expire": soa.expire, - "minimum": soa.minimum - }) - }, - RData::SRV(srv) => { - json!({ - "type": "SRV", - "priority": srv.priority, - "weight": srv.weight, - "port": srv.port, - "target": srv.target.to_string() - }) - }, - RData::SVCB(svcb) => { - let mut params = serde_json::Map::new(); - for (key, value) in svcb.iter_params() { - params.insert(key.to_string(), json!(base64::encode(value))); - } - json!({ - "type": "SVCB", - "priority": svcb.priority, - "target": svcb.target.to_string(), - "params": params - }) - }, - RData::WKS(wks) => { - json!({ - "type": "WKS", - "address": Ipv4Addr::from(wks.address).to_string(), - "protocol": wks.protocol, - "bit_map": base64::encode(&wks.bit_map) - }) - }, - - _ => json!({ - "type": format!("{:?}", record.rdata.type_code()), - "data": "Unhandled record type" - }), - } -} - -pub fn resource_record_to_json(record: &ResourceRecord) -> Result> { - Ok(json!({ - "name": record.name.to_string(), - "class": format!("{:?}", record.class), - "ttl": record.ttl, - "rdata": extract_rdata_for_json(record), - "cache_flush": record.cache_flush - })) -} - -pub fn construct_pubky_url(public_key: &str, domain: &str, path_segments: &[&str]) -> String { - // Construct the base URL - let mut url = format!("pubky://{}/pub/{}", public_key, domain); - - // Append each path segment, separated by '/' - for segment in path_segments { - if !segment.is_empty() { - url.push('/'); - url.push_str(segment); - } - } - - // Remove trailing slash if present - if url.ends_with('/') { - url.pop(); - } - - url -} - -/** -* Extract everything up to the first instance of "pub/" in a Pubky URL -* -* # Arguments -* * `full_url` - The full URL -* -* # Returns -* * `Some(String)` - The "pub/" part of the URL -* * `None` - If "pub/" is not found in the URL -*/ -pub fn get_list_url(full_url: &str) -> Option { - if let Some(index) = full_url.find("pub/") { - let end_index = index + "pub/".len(); - let substring = &full_url[..end_index]; - Some(substring.to_string()) - } else { - // "pub/" not found in the string - None - } -} diff --git a/rust/testing/main.rs b/rust/testing/main.rs deleted file mode 100644 index 4e0ed32..0000000 --- a/rust/testing/main.rs +++ /dev/null @@ -1,321 +0,0 @@ -use std::string::ToString; -use std::sync::Arc; -use once_cell::sync::Lazy; -use pkarr::{dns, Keypair, PublicKey, SignedPacket}; -use pkarr::bytes::Bytes; -use pkarr::dns::rdata::RData; -use pubky::PubkyClient; -use url::Url; -use std::str; - -static PUBKY_CLIENT: Lazy> = Lazy::new(|| { - // let custom_testnet = Testnet { - // bootstrap: vec!["http://localhost:6287".to_string()], - // nodes: vec![], - // }; - // - // let client = PubkyClient::builder() - // .testnet(&custom_testnet) - // .build(); - let client = PubkyClient::testnet(); - - Arc::new(client) -}); - -// static PUBKY_CLIENT: Lazy> = Lazy::new(|| { -// let custom_bootstrap = vec!["localhost:64630".to_string()]; -// -// let mut pkarr_settings = Settings::default(); -// pkarr_settings.dht.bootstrap = custom_bootstrap.clone().into(); -// pkarr_settings.resolvers = custom_bootstrap -// .iter() -// .flat_map(|resolver| resolver.to_socket_addrs()) -// .flatten() -// .collect::>() -// .into(); -// -// let client = PubkyClient::builder() -// .pkarr_settings(pkarr_settings) -// .build(); -// -// Arc::new(client) -// }); - -const HOMESERVER: &str = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"; -const SECRET_KEY: &str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - -#[tokio::main] -async fn main() { - let sign_in_res = signin_or_signup(SECRET_KEY, HOMESERVER).await; - println!("Sign In/Up Response: {:?}", sign_in_res); - // let res = publish("recordname".to_string(), "recordcontent".to_string(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string()).await; - // // println!("{:?}", res); - let public_key = &sign_in_res[1]; - let url = construct_pubky_url(public_key, "mydomain.com", &[]); - let put_res = put(&url, &"newcontent".to_string()).await; - println!("Put Response: {:?}", put_res); - let get_res = get(&url).await; - println!("Get Response: {:?}", get_res); - let list_res = list(url).await; - println!("List Response: {:?}", list_res); - let create_response = create_recovery_file(&SECRET_KEY, "password"); - println!("Create Response: {:?}", create_response); - let recovery_file = create_response[1].clone(); - let decrypt_response = decrypt_recovery_file(&recovery_file, "password"); - println!("Decrypt Response: {:?}", decrypt_response); -} - -pub fn create_recovery_file(secret_key: &str, passphrase: &str,) -> Vec { - if secret_key.is_empty() || passphrase.is_empty() { - return create_response_vector(true, "Secret key and passphrase must not be empty".to_string()); - } - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - let recovery_file_bytes = match PubkyClient::create_recovery_file(&keypair, &passphrase) { - Ok(bytes) => bytes, - Err(_) => return create_response_vector(true, "Failed to create recovery file".to_string()), - }; - let recovery_file = base64::encode(&recovery_file_bytes); - create_response_vector(false, recovery_file) -} - -pub fn decrypt_recovery_file(recovery_file: &str, passphrase: &str) -> Vec { - if recovery_file.is_empty() || passphrase.is_empty() { - return create_response_vector(true, "Recovery file and passphrase must not be empty".to_string()); - } - let recovery_file_bytes = match base64::decode(&recovery_file) { - Ok(bytes) => bytes, - Err(error) => return create_response_vector(true, format!("Failed to decode recovery file: {}", error)), - }; - let keypair = match PubkyClient::decrypt_recovery_file(&recovery_file_bytes, &passphrase) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, "Failed to decrypt recovery file".to_string()), - }; - let secret_key = get_secret_key_from_keypair(&keypair); - create_response_vector(false, secret_key) -} - - -pub async fn signin_or_signup(secret_key: &str, homeserver: &str) -> Vec { - let sign_in_res = sign_in(secret_key).await; - if sign_in_res[0] == "success" { - return sign_in_res; - } - let sign_up_res = sign_up(secret_key, homeserver).await; - sign_up_res -} - -pub async fn sign_up(secret_key: &str, homeserver: &str) -> Vec { - let client = PUBKY_CLIENT.clone(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - let homeserver_public_key = match PublicKey::try_from(homeserver) { - Ok(key) => key, - Err(error) => return create_response_vector(true, format!("Invalid homeserver public key: {}", error)), - }; - - match client.signup(&keypair, &homeserver_public_key).await { - Ok(session) => create_response_vector(false, session.pubky().to_string()), - Err(error) => create_response_vector(true, format!("signup failure: {}", error)), - } -} - -pub async fn sign_in(secret_key: &str) -> Vec { - let client = PUBKY_CLIENT.clone(); - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - match client.signin(&keypair).await { - Ok(session) => { - create_response_vector(false, session.pubky().to_string()) - }, - Err(error) => { - create_response_vector(true, format!("Failed to sign in: {}", error)) - } - } -} - -pub async fn publish(record_name: String, record_content: String, secret_key: String) -> Vec { - let client = PUBKY_CLIENT.clone(); - - let keypair = match get_keypair_from_secret_key(&secret_key) { - Ok(keypair) => keypair, - Err(error) => return create_response_vector(true, error), - }; - - let mut packet = dns::Packet::new_reply(0); - - let dns_name = match dns::Name::new(&record_name) { - Ok(name) => name, - Err(e) => return create_response_vector(true, format!("Failed to create DNS name: {}", e)), - }; - - let record_content_str: &str = record_content.as_str(); - - let txt_record = match record_content_str.try_into() { - Ok(value) => RData::TXT(value), - Err(e) => { - return create_response_vector(true, format!("Failed to convert string to TXT record: {}", e)) - } - }; - - packet.answers.push(dns::ResourceRecord::new( - dns_name, - dns::CLASS::IN, - 30, - txt_record, - )); - - match SignedPacket::from_packet(&keypair, &packet) { - Ok(signed_packet) => { - match client.pkarr().publish(&signed_packet).await { - Ok(()) => { - create_response_vector(false, keypair.public_key().to_string()) - } - Err(e) => { - create_response_vector(true, format!("Failed to publish: {}", e)) - } - } - } - Err(e) => { - create_response_vector(true, format!("Failed to create signed packet: {}", e)) - } - } -} - -pub fn get_keypair_from_secret_key(secret_key: &str) -> Result { - let bytes = match hex::decode(&secret_key) { - Ok(bytes) => bytes, - Err(_) => return Err("Failed to decode secret key".to_string()) - }; - - let secret_key_bytes: [u8; 32] = match bytes.try_into() { - Ok(secret_key) => secret_key, - Err(_) => { - return Err("Failed to convert secret key to 32-byte array".to_string()); - } - }; - - Ok(Keypair::from_secret_key(&secret_key_bytes)) -} - -pub fn create_response_vector(error: bool, data: String) -> Vec { - if error { - vec!["error".to_string(), data] - } else { - vec!["success".to_string(), data] - } -} - -pub async fn put(url: &String, content: &String) -> Vec { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - match client.put(parsed_url, &content.as_bytes()).await { - Ok(_) => create_response_vector(false, trimmed_url.to_string()), - Err(error) => { - create_response_vector(true, format!("Failed to put: {}", error)) - } - } -} - -pub async fn get(url: &String) -> Vec { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - - // Parse the URL and return error early if it fails - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - - // Perform the request and return error early if no data is returned - let result: Option = match client.get(parsed_url).await { - Ok(res) => res, - Err(_) => return create_response_vector(true, "Request failed".to_string()), - }; - - // If there are bytes, attempt to convert to UTF-8 - let bytes = match result { - Some(bytes) => bytes, - None => return create_response_vector(true, "No data returned".to_string()), - }; - - // Try to convert bytes to string and return error if it fails - let string = match str::from_utf8(&bytes) { - Ok(s) => s.to_string(), - Err(_) => return create_response_vector(true, "Invalid UTF-8 sequence".to_string()), - }; - - // If everything is successful, return the formatted response - create_response_vector(false, string) -} - -pub async fn list(url: String) -> Vec { - let client = PUBKY_CLIENT.clone(); - let trimmed_url = url.trim_end_matches('/'); - let parsed_url = match Url::parse(&trimmed_url) { - Ok(url) => url, - Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()), - }; - let list_builder = match client.list(parsed_url) { - Ok(list) => list, - Err(error) => return create_response_vector(true, format!("Failed to list: {}", error)), - }; - // Execute the non-Send part synchronously - let send_future = list_builder.send(); - let send_res = match send_future.await { - Ok(res) => res, - Err(error) => return create_response_vector(true, format!("Failed to send list request: {}", error)) - }; - let json_string = match serde_json::to_string(&send_res) { - Ok(json) => json, - Err(error) => return create_response_vector(true, format!("Failed to serialize JSON: {}", error)), - }; - create_response_vector(false, json_string) -} - -fn construct_pubky_url(public_key: &str, domain: &str, path_segments: &[&str]) -> String { - // Construct the base URL - let mut url = format!("pubky://{}/pub/{}", public_key, domain); - - // Append each path segment, separated by '/' - for segment in path_segments { - if !segment.is_empty() { - url.push('/'); - url.push_str(segment); - } - } - - // Remove trailing slash if present - if url.ends_with('/') { - url.pop(); - } - - url -} - -fn get_list_url(full_url: &str) -> Option { - if let Some(index) = full_url.find("pub/") { - // Add length of "pub/" to include it in the substring - let end_index = index + "pub/".len(); - let substring = &full_url[..end_index]; - Some(substring.to_string()) - } else { - // "pub/" not found in the string - None - } -} - -pub fn get_secret_key_from_keypair(keypair: &Keypair) -> String { - hex::encode(keypair.secret_key()) -} diff --git a/setup-local-android-bindings.js b/setup-local-android-bindings.js new file mode 100644 index 0000000..b14f92f --- /dev/null +++ b/setup-local-android-bindings.js @@ -0,0 +1,44 @@ +const fs = require('fs').promises; +const path = require('path'); + +const ktPath = 'rust/bindings/android/pubkymobile.kt'; +const ktDestinationPath = 'android/src/main/java/uniffi/pubkymobile/'; +const jniPath = 'rust/bindings/android/jniLibs'; +const jniDestinationPath = 'android/src/main/jniLibs/'; + +async function runSetup() { + try { + console.log('Removing existing files...'); + // Remove destination directories if they exist + await Promise.all([ + fs.rm(ktDestinationPath, { recursive: true, force: true }), + fs.rm(jniDestinationPath, { recursive: true, force: true }), + ]); + + console.log('Creating directories...'); + // Create destination directories if they don't exist + await Promise.all([ + fs.mkdir(ktDestinationPath, { recursive: true }), + fs.mkdir(jniDestinationPath, { recursive: true }), + ]); + + console.log('Copying Kotlin file...'); + // Copy Kotlin file to destination + const ktTargetPath = path.join(ktDestinationPath, 'pubkymobile.kt'); + await fs.copyFile(ktPath, ktTargetPath); + + console.log('Copying JNI libraries...'); + // Copy JNI libraries directory + await fs.cp(jniPath, jniDestinationPath, { recursive: true }); + + console.log('Android files copied successfully!'); + } catch (error) { + console.error('Error during setup:', error); + process.exit(1); + } +} + +runSetup().catch((error) => { + console.error('Unhandled error:', error); + process.exit(1); +}); diff --git a/setup-local-ios-bindings.js b/setup-local-ios-bindings.js new file mode 100644 index 0000000..fee0d8d --- /dev/null +++ b/setup-local-ios-bindings.js @@ -0,0 +1,49 @@ +const fs = require('fs').promises; +const path = require('path'); + +const frameworkPath = 'rust/bindings/ios/PubkyMobile.xcframework'; +const frameworkDestinationPath = 'ios/Frameworks'; +const swiftFilePath = 'rust/bindings/ios/pubkymobile.swift'; +const swiftDestinationPath = 'ios/'; + +async function runSetup() { + try { + console.log('Removing existing files...'); + // Remove destination directories if they exist + await Promise.all([ + fs.rm(frameworkDestinationPath, { recursive: true, force: true }), + fs.rm('ios/pubkymobile.swift', { recursive: true, force: true }), + ]); + + console.log('Creating directories...'); + // Create destination directories if they don't exist + await Promise.all([ + fs.mkdir(frameworkDestinationPath, { recursive: true }), + fs.mkdir(swiftDestinationPath, { recursive: true }), + ]); + + // Copy framework to destination + const frameworkTargetPath = path.join( + frameworkDestinationPath, + path.basename(frameworkPath) + ); + await fs.cp(frameworkPath, frameworkTargetPath, { recursive: true }); + + // Copy Swift file to destination + const swiftTargetPath = path.join( + swiftDestinationPath, + path.basename(swiftFilePath) + ); + await fs.copyFile(swiftFilePath, swiftTargetPath); + + console.log('Framework and Swift file copied successfully!'); + } catch (error) { + console.error('Error during setup:', error); + process.exit(1); + } +} + +runSetup().catch((error) => { + console.error('Unhandled error:', error); + process.exit(1); +}); diff --git a/setup-remote-android-bindings.js b/setup-remote-android-bindings.js new file mode 100644 index 0000000..5aa7a67 --- /dev/null +++ b/setup-remote-android-bindings.js @@ -0,0 +1,82 @@ +const fs = require('fs').promises; +const path = require('path'); +const simpleGit = require('simple-git'); + +// Configuration +const repoOwner = 'pubky'; +const repoName = 'pubky-core-mobile-sdk'; +const branch = 'main'; +const ktPath = 'bindings/android/pubkymobile.kt'; +const ktDestinationPath = 'android/src/main/java/uniffi/pubkymobile/'; +const jniPath = 'bindings/android/jniLibs'; +const jniDestinationPath = 'android/src/main/jniLibs/'; +const tempDir = 'temp'; + +async function runSetup() { + try { + console.log('Removing existing files...'); + // Remove destination directories if they exist & Clean up any lingering temporary directory + await Promise.all([ + fs.rm(ktDestinationPath, { recursive: true, force: true }), + fs.rm(jniDestinationPath, { recursive: true, force: true }), + fs.rm(tempDir, { recursive: true, force: true }), + ]); + + console.log('Creating directories...'); + // Create destination directories if they don't exist + await Promise.all([ + fs.mkdir(ktDestinationPath, { recursive: true }), + fs.mkdir(jniDestinationPath, { recursive: true }), + ]); + + // Initialize Git + const git = simpleGit(); + + console.log('Cloning repository...'); + // Clone the repository sparsely + await git.clone( + `https://github.com/${repoOwner}/${repoName}.git`, + tempDir, + ['--depth', '1', '--filter=blob:none', '--sparse', `--branch=${branch}`] + ); + + // Change directory to the cloned repository + const tempGit = simpleGit(tempDir); + + console.log('Setting up sparse checkout...'); + // Set sparse-checkout to include only the required directory + await tempGit.raw(['sparse-checkout', 'set', 'bindings/android']); + + console.log('Copying Kotlin file...'); + // Copy Kotlin file to destination + const ktSourcePath = path.join(tempDir, ktPath); + const ktTargetPath = path.join(ktDestinationPath, 'pubkymobile.kt'); + await fs.copyFile(ktSourcePath, ktTargetPath); + + console.log('Copying JNI libraries...'); + // Copy JNI libraries directory + const jniSourcePath = path.join(tempDir, jniPath); + const jniTargetPath = jniDestinationPath; + await fs.cp(jniSourcePath, jniTargetPath, { recursive: true }); + + console.log('Cleaning up...'); + // Clean up temporary directory + await fs.rm(tempDir, { recursive: true, force: true }); + + console.log('Android files downloaded and copied successfully!'); + } catch (error) { + console.error('Error during setup:', error); + // Try to clean up temp directory if it exists + try { + await fs.rm(tempDir, { recursive: true, force: true }); + } catch (cleanupError) { + console.error('Failed to clean up temporary directory:', cleanupError); + } + process.exit(1); + } +} + +runSetup().catch((error) => { + console.error('Unhandled error:', error); + process.exit(1); +}); diff --git a/setup-remote-ios-bindings.js b/setup-remote-ios-bindings.js new file mode 100644 index 0000000..0a0f9e5 --- /dev/null +++ b/setup-remote-ios-bindings.js @@ -0,0 +1,83 @@ +const fs = require('fs').promises; +const path = require('path'); +const simpleGit = require('simple-git'); + +// Configuration +const repoOwner = 'pubky'; +const repoName = 'pubky-core-mobile-sdk'; +const branch = 'main'; +const frameworkPath = 'bindings/ios/PubkyMobile.xcframework'; +const frameworkDestinationPath = 'ios/Frameworks'; +const swiftFilePath = 'bindings/ios/pubkymobile.swift'; +const swiftDestinationPath = 'ios/'; +const tempDir = 'temp'; + +async function runSetup() { + try { + console.log('Removing existing files...'); + // Remove destination directories if they exist & Clean up any lingering temporary directory + await Promise.all([ + fs.rm(frameworkDestinationPath, { recursive: true, force: true }), + fs.rm('ios/pubkymobile.swift', { recursive: true, force: true }), + fs.rm(tempDir, { recursive: true, force: true }), + ]); + + console.log('Creating directories...'); + // Create destination directories if they don't exist + await Promise.all([ + fs.mkdir(frameworkDestinationPath, { recursive: true }), + fs.mkdir(swiftDestinationPath, { recursive: true }), + ]); + + // Initialize Git + const git = simpleGit(); + + // Clone the repository sparsely + await git.clone( + `https://github.com/${repoOwner}/${repoName}.git`, + tempDir, + ['--depth', '1', '--filter=blob:none', '--sparse', `--branch=${branch}`] + ); + + // Change directory to the cloned repository + const tempGit = simpleGit(tempDir); + + // Set sparse-checkout to include only the required directory + await tempGit.raw(['sparse-checkout', 'set', 'bindings/ios']); + + // Copy framework to destination + const frameworkSourcePath = path.join(tempDir, frameworkPath); + const frameworkTargetPath = path.join( + frameworkDestinationPath, + path.basename(frameworkPath) + ); + await fs.cp(frameworkSourcePath, frameworkTargetPath, { recursive: true }); + + // Copy Swift file to destination + const swiftSourcePath = path.join(tempDir, swiftFilePath); + const swiftTargetPath = path.join( + swiftDestinationPath, + path.basename(swiftFilePath) + ); + await fs.copyFile(swiftSourcePath, swiftTargetPath); + + // Clean up temporary directory + await fs.rm(tempDir, { recursive: true, force: true }); + + console.log('Framework and Swift file downloaded and copied successfully!'); + } catch (error) { + console.error('Error during setup:', error); + // Try to clean up temp directory if it exists + try { + await fs.rm(tempDir, { recursive: true, force: true }); + } catch (cleanupError) { + console.error('Failed to clean up temporary directory:', cleanupError); + } + process.exit(1); + } +} + +runSetup().catch((error) => { + console.error('Unhandled error:', error); + process.exit(1); +}); diff --git a/setup-rust.js b/setup-rust.js new file mode 100644 index 0000000..942e522 --- /dev/null +++ b/setup-rust.js @@ -0,0 +1,62 @@ +const simpleGit = require('simple-git'); +const fs = require('fs').promises; +const path = require('path'); + +const rustDir = 'rust'; +const repoOwner = 'pubky'; +const repoName = 'pubky-core-mobile-sdk'; +const branch = 'main'; +const tempDir = 'temp'; + +async function setupRustDirectory() { + try { + // Check if rust directory exists + const rustExists = await fs + .access(rustDir) + .then(() => true) + .catch(() => false); + + if (!rustExists) { + console.log('Creating rust directory...'); + await fs.mkdir(rustDir); + + // Clone the repository directly into rust directory + const git = simpleGit(); + await git.clone( + `https://github.com/${repoOwner}/${repoName}.git`, + tempDir, + ['--depth', '1', `--branch=${branch}`] + ); + + // Move all contents from temp directory to rust directory + const tempContents = await fs.readdir(path.join(tempDir)); + await Promise.all( + tempContents.map(async (item) => { + if (item !== '.git') { + // Skip .git directory + const source = path.join(tempDir, item); + const dest = path.join(rustDir, item); + await fs.cp(source, dest, { recursive: true }); + } + }) + ); + + // Clean up temp directory + await fs.rm(tempDir, { recursive: true, force: true }); + console.log('Rust directory setup completed successfully!'); + } else { + console.log('Rust directory already exists, skipping setup...'); + } + } catch (error) { + console.error('Error during rust directory setup:', error); + // Try to clean up temp directory if it exists + try { + await fs.rm(tempDir, { recursive: true, force: true }); + } catch (cleanupError) { + console.error('Failed to clean up temporary directory:', cleanupError); + } + throw error; // Re-throw to be handled by the main try-catch + } +} + +setupRustDirectory(); diff --git a/yarn.lock b/yarn.lock index d67e7aa..db1a236 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2297,6 +2297,22 @@ __metadata: languageName: node linkType: hard +"@kwsites/file-exists@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/file-exists@npm:1.1.1" + dependencies: + debug: ^4.1.1 + checksum: 4ff945de7293285133aeae759caddc71e73c4a44a12fac710fdd4f574cce2671a3f89d8165fdb03d383cfc97f3f96f677d8de3c95133da3d0e12a123a23109fe + languageName: node + linkType: hard + +"@kwsites/promise-deferred@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/promise-deferred@npm:1.1.1" + checksum: 07455477a0123d9a38afb503739eeff2c5424afa8d3dbdcc7f9502f13604488a4b1d9742fc7288832a52a6422cf1e1c0a1d51f69a39052f14d27c9a0420b6629 + languageName: node + linkType: hard + "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": version: 5.1.1-v1 resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" @@ -3035,6 +3051,7 @@ __metadata: react-native: 0.75.3 react-native-builder-bob: ^0.30.2 release-it: ^15.0.0 + simple-git: ^3.27.0 turbo: ^1.10.7 typescript: ^5.2.2 peerDependencies: @@ -5147,7 +5164,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5": version: 4.3.7 resolution: "debug@npm:4.3.7" dependencies: @@ -11708,6 +11725,17 @@ __metadata: languageName: node linkType: hard +"simple-git@npm:^3.27.0": + version: 3.27.0 + resolution: "simple-git@npm:3.27.0" + dependencies: + "@kwsites/file-exists": ^1.1.1 + "@kwsites/promise-deferred": ^1.1.1 + debug: ^4.3.5 + checksum: bc602d67317a5421363f4cbe446bc71336387a7ea9864b23993dcbbd7e4847e346a234aa5b46bf9d80130d2448cbaeb21cf8f7b62572dce093fb4643ff7ffafd + languageName: node + linkType: hard + "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5"