From 68bf3f49fc386f3ca44d7f2745339c4c42ab786e Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 28 Aug 2023 12:22:06 +1000 Subject: [PATCH 01/64] feat: add working GroupInfo constructor --- index.d.ts | 85 +++++++++++++++++++++++++++- libsession-util | 2 +- src/addon.cpp | 9 +++ src/base_config.hpp | 38 +++++++++++++ src/group_info_config.cpp | 114 ++++++++++++++++++++++++++++++++++++++ src/group_info_config.hpp | 25 +++++++++ src/utilities.cpp | 11 ++++ src/utilities.hpp | 3 +- 8 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 src/group_info_config.cpp create mode 100644 src/group_info_config.hpp diff --git a/index.d.ts b/index.d.ts index d51d99c..9837823 100644 --- a/index.d.ts +++ b/index.d.ts @@ -53,7 +53,7 @@ declare module 'libsession_util_nodejs' { * */ - type BaseConfigWrapper = { + export type BaseConfigWrapper = { needsDump: () => boolean; needsPush: () => boolean; push: () => PushConfigResult; @@ -64,6 +64,11 @@ declare module 'libsession_util_nodejs' { currentHashes: () => Array; }; + export type GenericWrapperActionsCall = ( + wrapperId: A, + ...args: Parameters + ) => Promise>; + export type BaseConfigActions = | MakeActionCall | MakeActionCall @@ -363,4 +368,82 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall; + + /** + * + * GroupInfo wrapper logic + * + */ + + type GroupInfoShared = { + name: string | null; + createdAtSeconds: number | null; + deleteAttachBeforeSeconds: number | null; + deleteBeforeSeconds: number | null; + expirySeconds: number | null; + profilePicture: ProfilePicture | null; + }; + + export type GroupInfoGet = GroupInfoShared & { + // pubkeyHex: string; // The group "session id" (33 bytes), starting with 03 + isDestroyed: boolean; + }; + + export type GroupInfoSet = GroupInfoShared; + + type GroupInfoWrapper = BaseConfigWrapper & { + initGroup: ( + ed25519Pubkey: Uint8Array, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => void; + + // GroupInfo related methods + getInfo: () => GroupInfoGet | null; + setInfo: (info: GroupInfoSet) => GroupInfoGet; + destroy: () => void; + }; + + type AsyncGroupWrapper any> = ( + groupPk: GroupPubkeyType, + ...args: Parameters + ) => Promise>; + + type MakeGroupWrapperActionCalls = { + [Property in keyof Omit]: AsyncGroupWrapper; + }; + + export type GroupPubkeyType = `03${string}`; // type of a string which starts by the 03 prefixed used for closed group + + type MakeGroupActionCall = [ + B, + ...Parameters + ]; // all of the groupActionCalls need the pubkey of the group we are targetting + + export type GroupInfoWrapperActionsCalls = MakeGroupWrapperActionCalls & { + initGroup: ( + ed25519Pubkey: GroupPubkeyType, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => Promise; + }; + + export class GroupInfoWrapperNode extends BaseConfigWrapperNode { + constructor( + ed25519Pubkey: GroupPubkeyType, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ); + + // GroupInfo related methods + public getInfo: GroupInfoWrapper['getInfo']; + public setInfo: GroupInfoWrapper['setInfo']; + public destroy: GroupInfoWrapper['destroy']; + } + + export type GroupInfoActionsType = + | ['initGroup', GroupPubkeyType, Uint8Array | null, Uint8Array | null] + | MakeGroupActionCall + | MakeGroupActionCall + | MakeGroupActionCall; } diff --git a/libsession-util b/libsession-util index e3ccf29..8837103 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit e3ccf29db08aaf0b9bb6bbe72ae5967cd183a78d +Subproject commit 883710340a14b74ffbac482b8b4b41aadcad446e diff --git a/src/addon.cpp b/src/addon.cpp index b18466f..8d31850 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -2,17 +2,26 @@ #include "contacts_config.hpp" #include "convo_info_volatile_config.hpp" +#include "group_info_config.hpp" +// #include "group_keys_config.hpp" +// #include "group_members_config.hpp" #include "user_config.hpp" #include "user_groups_config.hpp" Napi::Object InitAll(Napi::Env env, Napi::Object exports) { using namespace session::nodeapi; + // User wrappers init UserConfigWrapper::Init(env, exports); ContactsConfigWrapper::Init(env, exports); UserGroupsWrapper::Init(env, exports); ConvoInfoVolatileWrapper::Init(env, exports); + // Group wrappers init + // GroupKeysWrapper::Init(env, exports); + GroupInfoWrapper::Init(env, exports); + // GroupMembersWrapper::Init(env, exports); + return exports; } diff --git a/src/base_config.hpp b/src/base_config.hpp index 901606a..368085a 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -104,6 +105,43 @@ class ConfigBaseImpl { }); } + // Constructs a shared_ptr of some config::ConfigBase-derived type, taking a secret key and + // optional dump. This is what most Config types require, but a subclass could replace this if + // it needs to do something else. + template < + typename Config, + std::enable_if_t, int> = 0> + static std::shared_ptr construct3Args( + const Napi::CallbackInfo& info, const std::string& class_name) { + return wrapExceptions(info, [&] { + if (!info.IsConstructCall()) + throw std::invalid_argument{ + "You need to call the constructor with the `new` syntax"}; + + assertInfoLength(info, 3); + + // we should get ed25519_pubkey as string (with 03 prefix), as first arg, secret key as + // second opt arg and optional dumped as third arg + assertIsString(info[0]); + assertIsUInt8ArrayOrNull(info[1]); + assertIsUInt8ArrayOrNull(info[2]); + std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new0"); + std::optional secret_key; + auto second = info[1]; + if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) + secret_key = toCppBufferView(second, class_name + ".new1"); + + std::optional dump; + auto third = info[2]; + if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) + dump = toCppBufferView(third, class_name + ".new2"); + + auto withoutPrefix = ed25519_pubkey_str.substr(2); + ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); + return std::make_shared(ed25519_pubkey, secret_key, dump); + }); + } + virtual ~ConfigBaseImpl() = default; // Accesses a reference the stored config instance as `std::shared_ptr` (if no template is diff --git a/src/group_info_config.cpp b/src/group_info_config.cpp new file mode 100644 index 0000000..08f2eb8 --- /dev/null +++ b/src/group_info_config.cpp @@ -0,0 +1,114 @@ +#include "group_info_config.hpp" + +#include + +#include "base_config.hpp" +#include "profile_pic.hpp" +#include "session/config/groups/info.hpp" +#include "session/types.hpp" + +namespace session::nodeapi { + +// namespace convo = config::convo; + +using config::groups::Info; + +// template <> +// struct toJs_impl { +// Napi::Object operator()(const Napi::Env& env, const convo::one_to_one& info_1o1) { + +// auto obj = Napi::Object::New(env); + +// obj["pubkeyHex"] = toJs(env, info_1o1.session_id); +// obj["unread"] = toJs(env, info_1o1.unread); +// obj["lastRead"] = toJs(env, info_1o1.last_read); + +// return obj; +// } +// }; + +void GroupInfoWrapper::Init(Napi::Env env, Napi::Object exports) { + InitHelper( + env, + exports, + "GroupInfoWrapperNode", + { + // group related methods + InstanceMethod("getInfo", &GroupInfoWrapper::getInfo), + InstanceMethod("setInfo", &GroupInfoWrapper::setInfo), + // InstanceMethod("destroy", &GroupInfoWrapper::destroy), + + }); +} + +GroupInfoWrapper::GroupInfoWrapper(const Napi::CallbackInfo& info) : + ConfigBaseImpl{construct3Args(info, "GroupsInfo")}, + Napi::ObjectWrap{info} {} + +// /** +// * ================================================= +// * ==================== GETTERS ==================== +// * ================================================= +// */ + +Napi::Value GroupInfoWrapper::getInfo(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + auto obj = Napi::Object::New(env); + + obj["name"] = toJs(env, config.get_name()); + obj["createdAtSeconds"] = toJs(env, config.get_created()); + obj["deleteAttachBeforeSeconds"] = toJs(env, config.get_delete_attach_before()); + obj["deleteBeforeSeconds"] = toJs(env, config.get_delete_before()); + + if (auto expiry = config.get_expiry_timer(); expiry) + obj["expirySeconds"] = toJs(env, expiry->count()); + obj["isDestroyed"] = toJs(env, config.is_destroyed()); + obj["profilePicture"] = object_from_profile_pic(env, config.get_profile_pic()); + + return obj; + }); +} + +Napi::Value GroupInfoWrapper::setInfo(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + auto arg = info[0]; + assertIsObject(arg); + auto obj = arg.As(); + + if (auto name = maybeNonemptyString(obj.Get("name"), "GroupInfoWrapper::setInfo name")) + config.set_name(*name); + + if (auto created = maybeNonemptyInt( + obj.Get("createdAtSeconds"), "GroupInfoWrapper::setInfo set_created")) + config.set_created(std::move(*created)); + + if (auto expiry = maybeNonemptyInt( + obj.Get("expirySeconds"), "GroupInfoWrapper::setInfo set_expiry_timer")) + config.set_expiry_timer(std::chrono::seconds{*expiry}); + + if (auto deleteBefore = maybeNonemptyInt( + obj.Get("deleteBeforeSeconds"), "GroupInfoWrapper::setInfo set_delete_before")) + config.set_delete_before(std::move(*deleteBefore)); + + if (auto deleteAttachBefore = maybeNonemptyInt( + obj.Get("deleteAttachBeforeSeconds"), + "GroupInfoWrapper::setInfo set_delete_attach_before")) + config.set_delete_attach_before(std::move(*deleteAttachBefore)); + + if (auto profilePicture = obj.Get("profilePicture")) { + auto profilePic = profile_pic_from_object(profilePicture); + config.set_profile_pic(profilePic); + } + + return this->getInfo(info); + }); +} + +// Napi::Value GroupInfoWrapper::destroy(const Napi::CallbackInfo& info) { +// return wrapResult(info, [&] { return config.erase_legacy_group(getStringArgs<1>(info)); +// }); +// } + +} // namespace session::nodeapi diff --git a/src/group_info_config.hpp b/src/group_info_config.hpp new file mode 100644 index 0000000..f253c0c --- /dev/null +++ b/src/group_info_config.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include "base_config.hpp" +#include "session/config/groups/info.hpp" + +namespace session::nodeapi { + +class GroupInfoWrapper : public ConfigBaseImpl, public Napi::ObjectWrap { + public: + static void Init(Napi::Env env, Napi::Object exports); + + explicit GroupInfoWrapper(const Napi::CallbackInfo& info); + + private: + session::config::groups::Info& config{get_config()}; + + // GroupInfo related methods + Napi::Value getInfo(const Napi::CallbackInfo& info); + Napi::Value setInfo(const Napi::CallbackInfo& info); + // Napi::Value destroy(); +}; + +} // namespace session::nodeapi diff --git a/src/utilities.cpp b/src/utilities.cpp index 9e5998a..018d19f 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -123,6 +123,17 @@ int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUnd throw std::invalid_argument{"Unsupported type for "s + identifier + ": expected a number"}; } +std::optional maybeNonemptyInt(Napi::Value x, const std::string& identifier) { + if (x.IsNull() || x.IsUndefined()) + return std::nullopt; + if (x.IsNumber()) { + auto num = x.As().Int64Value(); + return num; + } + + throw std::invalid_argument{"maybeNonemptyInt with invalid type, called from " + identifier}; +} + bool toCppBoolean(Napi::Value x, const std::string& identifier) { if (x.IsNull() || x.IsUndefined()) return false; diff --git a/src/utilities.hpp b/src/utilities.hpp index fd4e3c5..654a263 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -48,11 +48,12 @@ auto getStringArgs(const Napi::CallbackInfo& info) { return args; } - std::string toCppString(Napi::Value x, const std::string& identifier); ustring toCppBuffer(Napi::Value x, const std::string& identifier); ustring_view toCppBufferView(Napi::Value x, const std::string& identifier); int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUndefined = false); +std::optional maybeNonemptyInt(Napi::Value x, const std::string& identifier); + bool toCppBoolean(Napi::Value x, const std::string& identifier); // If the object is null/undef/empty returns nullopt, otherwise if a String returns a std::string of From bc9a98d6f1279d37779728d00c3ef7d9998e1d9e Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 28 Aug 2023 16:54:23 +1000 Subject: [PATCH 02/64] feat: add createGroup getGroup and destroyGroup --- index.d.ts | 44 +++++++++++++++++++++++++++++--------- src/base_config.hpp | 6 +++--- src/group_info_config.cpp | 24 ++++++--------------- src/group_info_config.hpp | 2 +- src/user_groups_config.cpp | 38 ++++++++++++++++++++++++++++++++ src/user_groups_config.hpp | 7 ++++++ 6 files changed, 89 insertions(+), 32 deletions(-) diff --git a/index.d.ts b/index.d.ts index 9837823..2a1a455 100644 --- a/index.d.ts +++ b/index.d.ts @@ -158,12 +158,13 @@ declare module 'libsession_util_nodejs' { export type ContactsWrapperActionsCalls = MakeWrapperActionCalls; - type ContactInfoShared = { + export type PriorityType = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned + + type ContactInfoShared = PriorityType & { id: string; name?: string; nickname?: string; profilePicture?: ProfilePicture; - priority: number; // -1 means hidden, 0 means normal, > 1 means pinned createdAtSeconds: number; // can only be set the first time a contact is created, a new change won't overide the value in the wrapper. // expirationMode: 'off' | 'disappearAfterRead' | 'disappearAfterSend'; // the same as defined in the disappearingBranch @@ -211,25 +212,33 @@ declare module 'libsession_util_nodejs' { roomCasePreserved: string; }; - export type CommunityInfo = CommunityDetails & { - pubkeyHex: string; - priority: number; // -1 means hidden, 0 means normal, > 0 means pinned. We currently don't support hidden communities on the client though - }; + export type CommunityInfo = CommunityDetails & + PriorityType & { + pubkeyHex: string; + }; export type LegacyGroupMemberInfo = { pubkeyHex: string; isAdmin: boolean; }; - export type LegacyGroupInfo = { + type BaseGroupInfo = PriorityType & { + joinedAtSeconds: number; // equivalent to the lastJoinedTimestamp in Session desktop but in seconds rather than MS + }; + + export type LegacyGroupInfo = BaseGroupInfo & { pubkeyHex: string; // The legacy group "session id" (33 bytes). name: string; // human-readable; this should normally always be set, but in theory could be set to an empty string. encPubkey: Uint8Array; // bytes (32 or empty) encSeckey: Uint8Array; // bytes (32 or empty) // disappearingTimerSeconds: number; // in seconds, 0 == disabled. - priority: number; // -1 means hidden, 0 means normal, > 1 means pinned. We currently don't support hidden groups on the client though members: Array; - joinedAtSeconds: number; // equivalent to the lastJoinedTimestamp in Session desktop but in seconds rather than MS + }; + + export type CreateGroupResult = BaseGroupInfo & { + pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. + secretKey: Uint8Array; + authSig: string; }; type UserGroupsWrapper = BaseConfigWrapper & { @@ -257,6 +266,13 @@ declare module 'libsession_util_nodejs' { getAllLegacyGroups: () => Array; setLegacyGroup: (info: LegacyGroupInfo) => boolean; eraseLegacyGroup: (pubkeyHex: string) => boolean; + + // Groups related methods + createGroup: () => CreateGroupResult; + getGroup: (pubkeyHex: GroupPubkeyType) => GroupInfoGet | null; + // getAllGroups: () => Array; + // setGroup: (info: LegacyGroupInfo) => boolean; + // eraseGroup: (pubkeyHex: GroupPubkeyType) => boolean; }; export type UserGroupsWrapperActionsCalls = MakeWrapperActionCalls; @@ -275,6 +291,13 @@ declare module 'libsession_util_nodejs' { public getAllLegacyGroups: UserGroupsWrapper['getAllLegacyGroups']; public setLegacyGroup: UserGroupsWrapper['setLegacyGroup']; public eraseLegacyGroup: UserGroupsWrapper['eraseLegacyGroup']; + + // groups related methods + public createGroup: UserGroupsWrapper['createGroup']; + public getGroup: UserGroupsWrapper['getGroup']; + // public getAllGroups: UserGroupsWrapper['getAllGroups']; + // public setGroup: UserGroupsWrapper['setGroup']; + // public eraseGroup: UserGroupsWrapper['eraseGroup']; } export type UserGroupsConfigActionsType = @@ -287,7 +310,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall; /** * diff --git a/src/base_config.hpp b/src/base_config.hpp index 368085a..1f4017c 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -125,16 +125,16 @@ class ConfigBaseImpl { assertIsString(info[0]); assertIsUInt8ArrayOrNull(info[1]); assertIsUInt8ArrayOrNull(info[2]); - std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new0"); + std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); std::optional secret_key; auto second = info[1]; if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) - secret_key = toCppBufferView(second, class_name + ".new1"); + secret_key = toCppBufferView(second, class_name + ".new.secret"); std::optional dump; auto third = info[2]; if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) - dump = toCppBufferView(third, class_name + ".new2"); + dump = toCppBufferView(third, class_name + ".new.dump"); auto withoutPrefix = ed25519_pubkey_str.substr(2); ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); diff --git a/src/group_info_config.cpp b/src/group_info_config.cpp index 08f2eb8..1e7415d 100644 --- a/src/group_info_config.cpp +++ b/src/group_info_config.cpp @@ -13,20 +13,6 @@ namespace session::nodeapi { using config::groups::Info; -// template <> -// struct toJs_impl { -// Napi::Object operator()(const Napi::Env& env, const convo::one_to_one& info_1o1) { - -// auto obj = Napi::Object::New(env); - -// obj["pubkeyHex"] = toJs(env, info_1o1.session_id); -// obj["unread"] = toJs(env, info_1o1.unread); -// obj["lastRead"] = toJs(env, info_1o1.last_read); - -// return obj; -// } -// }; - void GroupInfoWrapper::Init(Napi::Env env, Napi::Object exports) { InitHelper( env, @@ -106,9 +92,11 @@ Napi::Value GroupInfoWrapper::setInfo(const Napi::CallbackInfo& info) { }); } -// Napi::Value GroupInfoWrapper::destroy(const Napi::CallbackInfo& info) { -// return wrapResult(info, [&] { return config.erase_legacy_group(getStringArgs<1>(info)); -// }); -// } +Napi::Value GroupInfoWrapper::destroy(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + config.destroy_group(); + return this->getInfo(info); + }); +} } // namespace session::nodeapi diff --git a/src/group_info_config.hpp b/src/group_info_config.hpp index f253c0c..b45bfce 100644 --- a/src/group_info_config.hpp +++ b/src/group_info_config.hpp @@ -19,7 +19,7 @@ class GroupInfoWrapper : public ConfigBaseImpl, public Napi::ObjectWrap { } }; +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const group_info& info) { + auto obj = Napi::Object::New(env); + + obj["pubkeyHex"] = toJs(env, info.id); + obj["secretKey"] = toJs(env, info.secretkey); + obj["authSig"] = toJs(env, info.auth_sig); + obj["priority"] = toJs(env, info.priority); + obj["joinedAtSeconds"] = toJs(env, info.joined_at); + + return obj; + } +}; + void UserGroupsWrapper::Init(Napi::Env env, Napi::Object exports) { InitHelper( env, @@ -78,6 +94,14 @@ void UserGroupsWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("getAllLegacyGroups", &UserGroupsWrapper::getAllLegacyGroups), InstanceMethod("setLegacyGroup", &UserGroupsWrapper::setLegacyGroup), InstanceMethod("eraseLegacyGroup", &UserGroupsWrapper::eraseLegacyGroup), + + // Groups related methods + InstanceMethod("createGroup", &UserGroupsWrapper::createGroup), + InstanceMethod("getGroup", &UserGroupsWrapper::getGroup), + // InstanceMethod("getAllGroups", &UserGroupsWrapper::getAllGroups), + // InstanceMethod("setGroup", &UserGroupsWrapper::setGroup), + // InstanceMethod("eraseGroup", &UserGroupsWrapper::eraseGroup), + }); } @@ -237,4 +261,18 @@ Napi::Value UserGroupsWrapper::eraseLegacyGroup(const Napi::CallbackInfo& info) return wrapResult(info, [&] { return config.erase_legacy_group(getStringArgs<1>(info)); }); } +/** + * ================================================= + * ===================== GROUPS ==================== + * ================================================= + */ + +Napi::Value UserGroupsWrapper::createGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.create_group(); }); +} + +Napi::Value UserGroupsWrapper::getGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.get_group(getStringArgs<1>(info)); }); +} + } // namespace session::nodeapi diff --git a/src/user_groups_config.hpp b/src/user_groups_config.hpp index 7af3372..bbe12c3 100644 --- a/src/user_groups_config.hpp +++ b/src/user_groups_config.hpp @@ -28,6 +28,13 @@ class UserGroupsWrapper : public ConfigBaseImpl, public Napi::ObjectWrap Date: Wed, 30 Aug 2023 11:59:59 +1000 Subject: [PATCH 03/64] feat: wip of info and members group --- groups.d.ts | 116 +++++++++++++++ index.d.ts | 151 +------------------- shared.d.ts | 90 ++++++++++++ src/addon.cpp | 8 +- src/{ => groups}/group_info_config.cpp | 4 +- src/{ => groups}/group_info_config.hpp | 2 +- src/groups/group_members_config.cpp | 186 +++++++++++++++++++++++++ src/groups/group_members_config.hpp | 35 +++++ 8 files changed, 436 insertions(+), 156 deletions(-) create mode 100644 groups.d.ts create mode 100644 shared.d.ts rename src/{ => groups}/group_info_config.cpp (96%) rename src/{ => groups}/group_info_config.hpp (95%) create mode 100644 src/groups/group_members_config.cpp create mode 100644 src/groups/group_members_config.hpp diff --git a/groups.d.ts b/groups.d.ts new file mode 100644 index 0000000..ddc41dc --- /dev/null +++ b/groups.d.ts @@ -0,0 +1,116 @@ +/// + +declare module 'libsession_util_nodejs' { + /** + * + * Group Wrapper Logics + */ + + type GroupInfoShared = { + name: string | null; + createdAtSeconds: number | null; + deleteAttachBeforeSeconds: number | null; + deleteBeforeSeconds: number | null; + expirySeconds: number | null; + profilePicture: ProfilePicture | null; + }; + + export type GroupInfoGet = GroupInfoShared & { + isDestroyed: boolean; + }; + + export type GroupInfoSet = GroupInfoShared; + + type GroupInfoWrapper = BaseConfigWrapper & { + initGroup: ( + ed25519Pubkey: Uint8Array, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => void; + + // GroupInfo related methods + getInfo: () => GroupInfoGet | null; + setInfo: (info: GroupInfoSet) => GroupInfoGet; + destroy: () => void; + }; + + export type GroupInfoWrapperActionsCalls = MakeGroupWrapperActionCalls & { + initGroup: ( + ed25519Pubkey: GroupPubkeyType, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => Promise; + }; + + export class GroupInfoWrapperNode extends BaseConfigWrapperNode { + constructor( + ed25519Pubkey: GroupPubkeyType, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ); + + // GroupInfo related methods + public getInfo: GroupInfoWrapper['getInfo']; + public setInfo: GroupInfoWrapper['setInfo']; + public destroy: GroupInfoWrapper['destroy']; + } + + type GroupActionMap = Omit< + { [K in keyof T]: MakeGroupActionCall }, + BaseConfigFunctions + >; + + type GroupActionUnion = GroupActionMap[keyof GroupActionMap]; + + export type GroupInfoActionsType = GroupActionUnion; + + /** + * + * GroupMembers wrapper logic + * + */ + type GroupMemberShared = { + pubkeyHex: string; + name: string | null; + profilePicture: ProfilePicture | null; + }; + + export type GroupMemberGet = GroupMemberShared & { + invitePending: boolean; + inviteFailed: boolean; + promotionPending: boolean; + promotionFailed: boolean; + promoted: boolean; + }; + + type GroupMemberWrapper = BaseConfigWrapper & { + initGroup: ( + ed25519Pubkey: Uint8Array, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => void; + + // GroupMember related methods + get: (pubkeyHex: string) => GroupMemberGet | null; + getOrConstruct: (pubkeyHex: string) => GroupMemberGet; + getAll: () => Array; + + // setters + setName: (pubkeyHex: string, newName: string) => GroupMemberGet; + setInvited: (pubkeyHex: string, failed: boolean) => GroupMemberGet; + setPromoted: (pubkeyHex: string, failed: boolean) => GroupMemberGet; + setAccepted: (pubkeyHex: string) => GroupMemberGet; + setProfilePicture: (pubkeyHex: string, profilePicture: ProfilePicture) => GroupMemberGet; + + // eraser + erase: (pubkeyHex: string) => null; + }; + + export type GroupMemberWrapperActionsCalls = MakeGroupWrapperActionCalls & { + initGroup: ( + ed25519Pubkey: GroupPubkeyType, + secretKey: Uint8Array | null, + dump: Uint8Array | null + ) => Promise; + }; +} diff --git a/index.d.ts b/index.d.ts index 2a1a455..862d324 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,5 @@ +/// +/// declare module 'libsession_util_nodejs' { /** * This is quite a complex setup, but so far I didn't find an easier way to describe what we want to do with the wrappers and have strong typings. @@ -24,74 +26,6 @@ declare module 'libsession_util_nodejs' { * */ - /** - * - * Utilities - * - */ - - type AsyncWrapper any> = ( - ...args: Parameters - ) => Promise>; - - type MakeWrapperActionCalls = { - [Property in keyof Type]: AsyncWrapper; - }; - - export type ProfilePicture = { - url: string | null; - key: Uint8Array | null; - }; - - export type PushConfigResult = { data: Uint8Array; seqno: number; hashes: Array }; - - type MakeActionCall = [B, ...Parameters]; - - /** - * - * Base Config wrapper logic - * - */ - - export type BaseConfigWrapper = { - needsDump: () => boolean; - needsPush: () => boolean; - push: () => PushConfigResult; - dump: () => Uint8Array; - confirmPushed: (seqno: number, hash: string) => void; - merge: (toMerge: Array<{ hash: string; data: Uint8Array }>) => number; - storageNamespace: () => number; - currentHashes: () => Array; - }; - - export type GenericWrapperActionsCall = ( - wrapperId: A, - ...args: Parameters - ) => Promise>; - - export type BaseConfigActions = - | MakeActionCall - | MakeActionCall - | MakeActionCall - | MakeActionCall - | MakeActionCall - | MakeActionCall - | MakeActionCall - | MakeActionCall; - - export abstract class BaseConfigWrapperNode { - public needsDump: BaseConfigWrapper['needsDump']; - public needsPush: BaseConfigWrapper['needsPush']; - public push: BaseConfigWrapper['push']; - public dump: BaseConfigWrapper['dump']; - public confirmPushed: BaseConfigWrapper['confirmPushed']; - public merge: BaseConfigWrapper['merge']; - public storageNamespace: BaseConfigWrapper['storageNamespace']; - public currentHashes: BaseConfigWrapper['currentHashes']; - } - - export type BaseWrapperActionsCalls = MakeWrapperActionCalls; - /** * * User config wrapper logic @@ -311,7 +245,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall; /** * @@ -392,82 +327,4 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall; - - /** - * - * GroupInfo wrapper logic - * - */ - - type GroupInfoShared = { - name: string | null; - createdAtSeconds: number | null; - deleteAttachBeforeSeconds: number | null; - deleteBeforeSeconds: number | null; - expirySeconds: number | null; - profilePicture: ProfilePicture | null; - }; - - export type GroupInfoGet = GroupInfoShared & { - // pubkeyHex: string; // The group "session id" (33 bytes), starting with 03 - isDestroyed: boolean; - }; - - export type GroupInfoSet = GroupInfoShared; - - type GroupInfoWrapper = BaseConfigWrapper & { - initGroup: ( - ed25519Pubkey: Uint8Array, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => void; - - // GroupInfo related methods - getInfo: () => GroupInfoGet | null; - setInfo: (info: GroupInfoSet) => GroupInfoGet; - destroy: () => void; - }; - - type AsyncGroupWrapper any> = ( - groupPk: GroupPubkeyType, - ...args: Parameters - ) => Promise>; - - type MakeGroupWrapperActionCalls = { - [Property in keyof Omit]: AsyncGroupWrapper; - }; - - export type GroupPubkeyType = `03${string}`; // type of a string which starts by the 03 prefixed used for closed group - - type MakeGroupActionCall = [ - B, - ...Parameters - ]; // all of the groupActionCalls need the pubkey of the group we are targetting - - export type GroupInfoWrapperActionsCalls = MakeGroupWrapperActionCalls & { - initGroup: ( - ed25519Pubkey: GroupPubkeyType, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => Promise; - }; - - export class GroupInfoWrapperNode extends BaseConfigWrapperNode { - constructor( - ed25519Pubkey: GroupPubkeyType, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ); - - // GroupInfo related methods - public getInfo: GroupInfoWrapper['getInfo']; - public setInfo: GroupInfoWrapper['setInfo']; - public destroy: GroupInfoWrapper['destroy']; - } - - export type GroupInfoActionsType = - | ['initGroup', GroupPubkeyType, Uint8Array | null, Uint8Array | null] - | MakeGroupActionCall - | MakeGroupActionCall - | MakeGroupActionCall; } diff --git a/shared.d.ts b/shared.d.ts new file mode 100644 index 0000000..8d8606e --- /dev/null +++ b/shared.d.ts @@ -0,0 +1,90 @@ +declare module 'libsession_util_nodejs' { + type AsyncWrapper any> = ( + ...args: Parameters + ) => Promise>; + + type MakeWrapperActionCalls = { + [Property in keyof Type]: AsyncWrapper; + }; + + export type ProfilePicture = { + url: string | null; + key: Uint8Array | null; + }; + + export type PushConfigResult = { data: Uint8Array; seqno: number; hashes: Array }; + + type MakeActionCall = [B, ...Parameters]; + + /** + * + * Base Config wrapper logic + * + */ + + export type BaseConfigWrapper = { + needsDump: () => boolean; + needsPush: () => boolean; + push: () => PushConfigResult; + dump: () => Uint8Array; + confirmPushed: (seqno: number, hash: string) => void; + merge: (toMerge: Array<{ hash: string; data: Uint8Array }>) => number; + storageNamespace: () => number; + currentHashes: () => Array; + }; + + type BaseConfigFunctions = + | 'needsDump' + | 'needsPush' + | 'push' + | 'dump' + | 'confirmPushed' + | 'merge' + | 'needsPush' + | 'storageNamespace' + | 'currentHashes'; + + export type GenericWrapperActionsCall = ( + wrapperId: A, + ...args: Parameters + ) => Promise>; + + export type BaseConfigActions = + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall; + + export abstract class BaseConfigWrapperNode { + public needsDump: BaseConfigWrapper['needsDump']; + public needsPush: BaseConfigWrapper['needsPush']; + public push: BaseConfigWrapper['push']; + public dump: BaseConfigWrapper['dump']; + public confirmPushed: BaseConfigWrapper['confirmPushed']; + public merge: BaseConfigWrapper['merge']; + public storageNamespace: BaseConfigWrapper['storageNamespace']; + public currentHashes: BaseConfigWrapper['currentHashes']; + } + + export type BaseWrapperActionsCalls = MakeWrapperActionCalls; + + export type GroupPubkeyType = `03${string}`; // type of a string which starts by the 03 prefixed used for closed group + + type MakeGroupActionCall = [ + B, + ...Parameters + ]; // all of the groupActionCalls need the pubkey of the group we are targetting + + type AsyncGroupWrapper any> = ( + groupPk: GroupPubkeyType, + ...args: Parameters + ) => Promise>; + + type MakeGroupWrapperActionCalls = { + [Property in keyof Omit]: AsyncGroupWrapper; + }; +} diff --git a/src/addon.cpp b/src/addon.cpp index 8d31850..d34be1e 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -2,9 +2,8 @@ #include "contacts_config.hpp" #include "convo_info_volatile_config.hpp" -#include "group_info_config.hpp" -// #include "group_keys_config.hpp" -// #include "group_members_config.hpp" +#include "groups/group_info_config.hpp" +#include "groups/group_members_config.hpp" #include "user_config.hpp" #include "user_groups_config.hpp" @@ -18,9 +17,8 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { ConvoInfoVolatileWrapper::Init(env, exports); // Group wrappers init - // GroupKeysWrapper::Init(env, exports); GroupInfoWrapper::Init(env, exports); - // GroupMembersWrapper::Init(env, exports); + GroupMembersWrapper::Init(env, exports); return exports; } diff --git a/src/group_info_config.cpp b/src/groups/group_info_config.cpp similarity index 96% rename from src/group_info_config.cpp rename to src/groups/group_info_config.cpp index 1e7415d..cca42d2 100644 --- a/src/group_info_config.cpp +++ b/src/groups/group_info_config.cpp @@ -9,8 +9,6 @@ namespace session::nodeapi { -// namespace convo = config::convo; - using config::groups::Info; void GroupInfoWrapper::Init(Napi::Env env, Napi::Object exports) { @@ -22,7 +20,7 @@ void GroupInfoWrapper::Init(Napi::Env env, Napi::Object exports) { // group related methods InstanceMethod("getInfo", &GroupInfoWrapper::getInfo), InstanceMethod("setInfo", &GroupInfoWrapper::setInfo), - // InstanceMethod("destroy", &GroupInfoWrapper::destroy), + InstanceMethod("destroy", &GroupInfoWrapper::destroy), }); } diff --git a/src/group_info_config.hpp b/src/groups/group_info_config.hpp similarity index 95% rename from src/group_info_config.hpp rename to src/groups/group_info_config.hpp index b45bfce..af49615 100644 --- a/src/group_info_config.hpp +++ b/src/groups/group_info_config.hpp @@ -2,7 +2,7 @@ #include -#include "base_config.hpp" +#include "../base_config.hpp" #include "session/config/groups/info.hpp" namespace session::nodeapi { diff --git a/src/groups/group_members_config.cpp b/src/groups/group_members_config.cpp new file mode 100644 index 0000000..1e5c2bb --- /dev/null +++ b/src/groups/group_members_config.cpp @@ -0,0 +1,186 @@ +#include "group_members_config.hpp" + +#include + +#include "../base_config.hpp" +#include "../profile_pic.hpp" +#include "session/config/groups/members.hpp" +#include "session/types.hpp" + +namespace session::nodeapi { + +using config::groups::Members; +using session::config::groups::member; + +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const member& info) { + auto obj = Napi::Object::New(env); + + obj["pubkeyHex"] = toJs(env, info.session_id); + obj["name"] = toJs(env, info.name); + obj["profilePicture"] = toJs(env, info.profile_picture); + obj["invitePending"] = toJs(env, info.invite_pending()); + obj["inviteFailed"] = toJs(env, info.invite_failed()); + obj["promotionPending"] = toJs(env, info.promotion_pending()); + obj["promotionFailed"] = toJs(env, info.promotion_failed()); + obj["promoted"] = toJs(env, info.promoted()); + + return obj; + } +}; + +void GroupMembersWrapper::Init(Napi::Env env, Napi::Object exports) { + InitHelper( + env, + exports, + "GroupMembersWrapperNode", + { + // group related methods + InstanceMethod("get", &GroupMembersWrapper::get), + InstanceMethod("getOrConstruct", &GroupMembersWrapper::getOrConstruct), + InstanceMethod("getAll", &GroupMembersWrapper::getAll), + InstanceMethod("setName", &GroupMembersWrapper::setName), + InstanceMethod("setInvited", &GroupMembersWrapper::setInvited), + InstanceMethod("setAccepted", &GroupMembersWrapper::setAccepted), + InstanceMethod("setPromoted", &GroupMembersWrapper::setPromoted), + InstanceMethod("setProfilePicture", &GroupMembersWrapper::setProfilePicture), + InstanceMethod("erase", &GroupMembersWrapper::erase), + + }); +} + +GroupMembersWrapper::GroupMembersWrapper(const Napi::CallbackInfo& info) : + ConfigBaseImpl{construct3Args(info, "GroupsMembers")}, + Napi::ObjectWrap{info} {} + +/** + * ================================================= + * ==================== GETTERS ==================== + * ================================================= + */ + +Napi::Value GroupMembersWrapper::get(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::get"); + + return config.get(pubkeyHex); + }); +} + +Napi::Value GroupMembersWrapper::getOrConstruct(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::getOrConstruct"); + + return config.get_or_construct(pubkeyHex); + }); +} + +Napi::Value GroupMembersWrapper::getAll(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 0); + + std::vector allMembers; + for (auto& member : config) { + allMembers.push_back(member); + } + + return allMembers; + }); +} + +Napi::Value GroupMembersWrapper::setName(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsString(info[1]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setName1"); + auto newName = toCppString(info[1], "GroupMembersWrapper::setName2"); + auto m = config.get_or_construct(pubkeyHex); + m.set_name(newName); + + return m; + }); +} + +Napi::Value GroupMembersWrapper::setInvited(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsBoolean(info[1]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setInvited1"); + auto failed = toCppBoolean(info[1], "GroupMembersWrapper::setInvited2"); + auto m = config.get_or_construct(pubkeyHex); + m.set_invited(failed); + + return m; + }); +} + +Napi::Value GroupMembersWrapper::setAccepted(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setAccepted"); + auto m = config.get_or_construct(pubkeyHex); + m.set_accepted(); + + return m; + }); +} + +Napi::Value GroupMembersWrapper::setPromoted(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsBoolean(info[1]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setPromoted1"); + auto failed = toCppBoolean(info[1], "GroupMembersWrapper::setPromoted2"); + auto m = config.get_or_construct(pubkeyHex); + m.set_promoted(failed); + + return m; + }); +} + +Napi::Value GroupMembersWrapper::setProfilePicture(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsObject(info[1]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setAccepted"); + auto profilePicture = profile_pic_from_object(info[1]); + + auto m = config.get_or_construct(pubkeyHex); + m.profile_picture = profilePicture; + config.set(m); + + return m; + }); +} + +Napi::Value GroupMembersWrapper::erase(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::erase"); + return config.erase(pubkeyHex); + }); +} + +} // namespace session::nodeapi diff --git a/src/groups/group_members_config.hpp b/src/groups/group_members_config.hpp new file mode 100644 index 0000000..6ca6aab --- /dev/null +++ b/src/groups/group_members_config.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "../base_config.hpp" +#include "session/config/groups/members.hpp" + +namespace session::nodeapi { + +class GroupMembersWrapper : public ConfigBaseImpl, public Napi::ObjectWrap { + public: + static void Init(Napi::Env env, Napi::Object exports); + + explicit GroupMembersWrapper(const Napi::CallbackInfo& info); + + private: + session::config::groups::Members& config{get_config()}; + + // GroupMembers related methods + Napi::Value get(const Napi::CallbackInfo& info); + Napi::Value getOrConstruct(const Napi::CallbackInfo& info); + Napi::Value getAll(const Napi::CallbackInfo& info); + + // setters + Napi::Value setName(const Napi::CallbackInfo& info); + Napi::Value setInvited(const Napi::CallbackInfo& info); + Napi::Value setAccepted(const Napi::CallbackInfo& info); + Napi::Value setPromoted(const Napi::CallbackInfo& info); + Napi::Value setProfilePicture(const Napi::CallbackInfo& info); + + // eraser + Napi::Value erase(const Napi::CallbackInfo& info); +}; + +} // namespace session::nodeapi From 1ba3a4fe8165b2cfd93dee81de9a23355d67dc43 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 31 Aug 2023 11:19:04 +1000 Subject: [PATCH 04/64] feat: wip of groupkeys wrapper --- src/addon.cpp | 2 + src/base_config.hpp | 12 --- src/config_sig.hpp | 131 +++++++++++++++++++++++++++++++ src/groups/group_keys_config.cpp | 98 +++++++++++++++++++++++ src/groups/group_keys_config.hpp | 34 ++++++++ 5 files changed, 265 insertions(+), 12 deletions(-) create mode 100644 src/config_sig.hpp create mode 100644 src/groups/group_keys_config.cpp create mode 100644 src/groups/group_keys_config.hpp diff --git a/src/addon.cpp b/src/addon.cpp index d34be1e..3f652a6 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -3,6 +3,7 @@ #include "contacts_config.hpp" #include "convo_info_volatile_config.hpp" #include "groups/group_info_config.hpp" +#include "groups/group_keys_config.hpp" #include "groups/group_members_config.hpp" #include "user_config.hpp" #include "user_groups_config.hpp" @@ -19,6 +20,7 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { // Group wrappers init GroupInfoWrapper::Init(env, exports); GroupMembersWrapper::Init(env, exports); + GroupKeysWrapper::Init(env, exports); return exports; } diff --git a/src/base_config.hpp b/src/base_config.hpp index 1f4017c..627b14b 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -157,18 +157,6 @@ class ConfigBaseImpl { "Error retrieving config: config instance is not of the requested type"}; } - // Same as above, but return a shared ptr. - template < - typename T = config::ConfigBase, - std::enable_if_t, int> = 0> - std::shared_ptr config_ptr() { - assert(conf_); // should not be possible to construct without this set - if (auto t = std::dynamic_pointer_cast(conf_)) - return t; - throw std::invalid_argument{ - "Error retrieving config: config instance is not of the requested type"}; - } - // Helper function for doing the subtype napi Init call. This sets up the class registration, // sets it in the exports, and appends the base methods and properties (needsDump, etc.) to the // given methods/properties list. diff --git a/src/config_sig.hpp b/src/config_sig.hpp new file mode 100644 index 0000000..db02ac4 --- /dev/null +++ b/src/config_sig.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include + +#include "session/config/base.hpp" +#include "session/types.hpp" +#include "utilities.hpp" + +using ustring_view = std::basic_string_view; + +namespace session::nodeapi { + +class ConfigSigImpl; +template +inline constexpr bool is_derived_napi_wrapper = + std::is_base_of_v&& std::is_base_of_v, T>; + +/// Base implementation class for config types; this provides the napi wrappers for the base +/// methods. Subclasses should inherit from this (alongside Napi::ObjectWrap) +/// and wrap their method list argument in `DefineClass` with a call to +/// `ConfigSigImpl::WithBaseMethods({...})` to have the base methods added to the derived +/// type appropriately. +class ConfigSigImpl { + std::shared_ptr conf_; + + public: + // Called from a sub-type's Init function (typically indirectly, via InitHelper) to add the base + // class properties/methods to the type. + template , int> = 0> + static std::vector WithBaseMethods( + std::vector properties) { + std::unordered_set seen; + for (const napi_property_descriptor& prop : properties) + if (prop.utf8name) + seen.emplace(prop.utf8name); + + return properties; + } + + protected: + // Constructor (callable from a subclass): the wrapper subclass constructs its + // ConfigSig-derived shared_ptr during *its* construction, passing it here. + ConfigSigImpl(std::shared_ptr conf) : conf_{std::move(conf)} { + if (!conf_) + throw std::invalid_argument{ + "ConfigSigImpl initialization requires a live ConfigSig pointer"}; + } + + // Constructs a shared_ptr of some config::ConfigBase-derived type, taking a secret key and + // optional dump. This is what most Config types require, but a subclass could replace this if + // it needs to do something else. + template < + typename Config, + std::enable_if_t, int> = 0> + static std::shared_ptr constructFromKeys( + const Napi::CallbackInfo& info, const std::string& class_name) { + return wrapExceptions(info, [&] { + if (!info.IsConstructCall()) + throw std::invalid_argument{ + "You need to call the constructor with the `new` syntax"}; + + assertInfoLength(info, 6); + + // types come from constructor of Keys::Keys + assertIsUInt8Array(info[0]); // user_ed25519_secretkey + assertIsUInt8Array(info[1]); // group_ed25519_pubkey + assertIsUInt8ArrayOrNull(info[2]); // group_ed25519_secretkey + assertIsUInt8ArrayOrNull(info[3]); // dumped + assertIsUInt8ArrayOrNull(info[4]); // dumped + assertIsUInt8ArrayOrNull(info[5]); // dumped + + std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); + std::optional secret_key; + auto second = info[1]; + if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) + secret_key = toCppBufferView(second, class_name + ".new.secret"); + + std::optional dump; + auto third = info[2]; + if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) + dump = toCppBufferView(third, class_name + ".new.dump"); + + auto withoutPrefix = ed25519_pubkey_str.substr(2); + ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); + return std::make_shared(ed25519_pubkey, secret_key, dump); + }); + } + + virtual ~ConfigSigImpl() = default; + + // Accesses a reference the stored config instance as `std::shared_ptr` (if no template is + // specified then as the base ConfigSig type). `T` must be a subclass of ConfigSig for this + // to compile. Throws std::logic_error if not set. Throws std::invalid_argument if the + // instance is not castable to a `T`. + template , int> = 0> + T& get_config() { + assert(conf_); // should not be possible to construct without this set + if (auto* t = dynamic_cast(conf_.get())) + return *t; + throw std::invalid_argument{ + "Error retrieving config: config instance is not of the requested type"}; + } + + // Helper function for doing the subtype napi Init call. This sets up the class registration, + // sets it in the exports, and appends the base methods and properties (needsDump, etc.) to the + // given methods/properties list. + template , int> = 0> + static void InitHelper( + Napi::Env env, + Napi::Object exports, + const char* class_name, + std::vector properties) { + + Napi::Function cls = + T::DefineClass(env, class_name, WithBaseMethods(std::move(properties))); + + auto ref = std::make_unique(); + *ref = Napi::Persistent(cls); + env.SetInstanceData(ref.release()); + + exports.Set(class_name, cls); + } +}; + +} // namespace session::nodeapi diff --git a/src/groups/group_keys_config.cpp b/src/groups/group_keys_config.cpp new file mode 100644 index 0000000..e32ae54 --- /dev/null +++ b/src/groups/group_keys_config.cpp @@ -0,0 +1,98 @@ +#include "group_keys_config.hpp" + +#include + +#include "../base_config.hpp" +#include "../profile_pic.hpp" +#include "session/config/groups/keys.hpp" +#include "session/types.hpp" + +namespace session::nodeapi { + +static InitHelper(Napi::Env env, Napi::Object exports) { + Napi::Function cls = T::DefineClass(env, class_name, WithBaseMethods(std::move(properties))); + + auto ref = std::make_unique(); + *ref = Napi::Persistent(cls); + env.SetInstanceData(ref.release()); + + exports.Set(class_name, cls); +} + +using config::groups::Keys; + +void GroupKeysWrapper::Init(Napi::Env env, Napi::Object exports) { + InitHelper( + env, + exports, + "GroupKeysWrapperNode", + { + // group related methods + InstanceMethod("get", &GroupKeysWrapper::get), + // InstanceMethod("getOrConstruct", &GroupKeysWrapper::getOrConstruct), + // InstanceMethod("getAll", &GroupKeysWrapper::getAll), + // InstanceMethod("setName", &GroupKeysWrapper::setName), + + }); +} + +GroupKeysWrapper::GroupKeysWrapper(const Napi::CallbackInfo& info) : + Napi::ObjectWrap{info} { + return wrapExceptions(info, [&] { + if (!info.IsConstructCall()) + throw std::invalid_argument{"You need to call the constructor with the `new` syntax"}; + auto class_name = "GroupKeys"s; + assertInfoLength(info, 3); + + // we should get ed25519_pubkey as string (with 03 prefix), as first arg, secret key as + // second opt arg and optional dumped as third arg + assertIsString(info[0]); + assertIsUInt8ArrayOrNull(info[1]); + assertIsUInt8ArrayOrNull(info[2]); + std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); + std::optional secret_key; + auto second = info[1]; + if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) + secret_key = toCppBufferView(second, class_name + ".new.secret"); + + std::optional dump; + auto third = info[2]; + if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) + dump = toCppBufferView(third, class_name + ".new.dump"); + + auto withoutPrefix = ed25519_pubkey_str.substr(2); + ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); + this->config = std::make_shared(ed25519_pubkey, secret_key, dump); + }); +} + +/** + * ================================================= + * ==================== GETTERS ==================== + * ================================================= + */ + +// Napi::Value GroupKeysWrapper::get(const Napi::CallbackInfo& info) { +// return wrapResult(info, [&] { +// auto env = info.Env(); +// assertInfoLength(info, 1); +// assertIsString(info[0]); + +// auto pubkeyHex = toCppString(info[0], "GroupKeysWrapper::get"); + +// return config.get(pubkeyHex); +// }); +// } + +// Napi::Value GroupKeysWrapper::getOrConstruct(const Napi::CallbackInfo& info) { +// return wrapResult(info, [&] { +// auto env = info.Env(); +// assertInfoLength(info, 1); +// assertIsString(info[0]); + +// auto pubkeyHex = toCppString(info[0], "GroupKeysWrapper::getOrConstruct"); + +// return config.get_or_construct(pubkeyHex); +// }); +// } +} // namespace session::nodeapi diff --git a/src/groups/group_keys_config.hpp b/src/groups/group_keys_config.hpp new file mode 100644 index 0000000..d3e3e55 --- /dev/null +++ b/src/groups/group_keys_config.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "../base_config.hpp" +#include "session/config/groups/keys.hpp" + +namespace session::nodeapi { + +class GroupKeysWrapper : public Napi::ObjectWrap { + public: + static void Init(Napi::Env env, Napi::Object exports); + + explicit GroupKeysWrapper(const Napi::CallbackInfo& info); + + private: + std::shared_ptr config; + // GroupKeys related methods + Napi::Value get(const Napi::CallbackInfo& info); + // Napi::Value getOrConstruct(const Napi::CallbackInfo& info); + // Napi::Value getAll(const Napi::CallbackInfo& info); + + // // setters + // Napi::Value setName(const Napi::CallbackInfo& info); + // Napi::Value setInvited(const Napi::CallbackInfo& info); + // Napi::Value setAccepted(const Napi::CallbackInfo& info); + // Napi::Value setPromoted(const Napi::CallbackInfo& info); + // Napi::Value setProfilePicture(const Napi::CallbackInfo& info); + + // // eraser + // Napi::Value erase(const Napi::CallbackInfo& info); +}; + +} // namespace session::nodeapi From e6d7aaec4db5b147ed1f4f22367cc3955cbbb811 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 1 Sep 2023 09:53:21 +1000 Subject: [PATCH 05/64] feat: add metagroup wrapper compiling with some methods only --- index.d.ts | 7 +- src/addon.cpp | 8 +- src/groups/meta_group.cpp | 25 ++++++ src/groups/meta_group.hpp | 32 ++++++++ src/groups/meta_group_wrapper.cpp | 26 +++++++ src/groups/meta_group_wrapper.hpp | 47 ++++++++++++ src/meta/meta_base.cpp | 11 +++ src/meta/meta_base.hpp | 15 ++++ src/meta/meta_base_wrapper.cpp | 3 + src/meta/meta_base_wrapper.hpp | 89 ++++++++++++++++++++++ {groups => types/groups}/groupinfo.d.ts | 0 {groups => types/groups}/groupmembers.d.ts | 0 {groups => types/groups}/index.d.ts | 1 + types/groups/metagroup.d.ts | 48 ++++++++++++ shared.d.ts => types/shared.d.ts | 8 +- {user => types/user}/contacts.d.ts | 2 + {user => types/user}/convovolatile.d.ts | 2 + {user => types/user}/index.d.ts | 0 {user => types/user}/userconfig.d.ts | 2 + {user => types/user}/usergroups.d.ts | 0 20 files changed, 314 insertions(+), 12 deletions(-) create mode 100644 src/groups/meta_group.cpp create mode 100644 src/groups/meta_group.hpp create mode 100644 src/groups/meta_group_wrapper.cpp create mode 100644 src/groups/meta_group_wrapper.hpp create mode 100644 src/meta/meta_base.cpp create mode 100644 src/meta/meta_base.hpp create mode 100644 src/meta/meta_base_wrapper.cpp create mode 100644 src/meta/meta_base_wrapper.hpp rename {groups => types/groups}/groupinfo.d.ts (100%) rename {groups => types/groups}/groupmembers.d.ts (100%) rename {groups => types/groups}/index.d.ts (67%) create mode 100644 types/groups/metagroup.d.ts rename shared.d.ts => types/shared.d.ts (92%) rename {user => types/user}/contacts.d.ts (97%) rename {user => types/user}/convovolatile.d.ts (98%) rename {user => types/user}/index.d.ts (100%) rename {user => types/user}/userconfig.d.ts (97%) rename {user => types/user}/usergroups.d.ts (100%) diff --git a/index.d.ts b/index.d.ts index f357ced..d771f6a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,7 @@ -/// -/// -/// +/// +/// +/// + declare module 'libsession_util_nodejs' { /** * This is quite a complex setup, but so far I didn't find an easier way to describe what we want to do with the wrappers and have strong typings. diff --git a/src/addon.cpp b/src/addon.cpp index 3f652a6..75b8ff6 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -2,9 +2,7 @@ #include "contacts_config.hpp" #include "convo_info_volatile_config.hpp" -#include "groups/group_info_config.hpp" -#include "groups/group_keys_config.hpp" -#include "groups/group_members_config.hpp" +#include "groups/meta_group_wrapper.hpp" #include "user_config.hpp" #include "user_groups_config.hpp" @@ -18,9 +16,7 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { ConvoInfoVolatileWrapper::Init(env, exports); // Group wrappers init - GroupInfoWrapper::Init(env, exports); - GroupMembersWrapper::Init(env, exports); - GroupKeysWrapper::Init(env, exports); + MetaGroupWrapper::Init(env, exports); return exports; } diff --git a/src/groups/meta_group.cpp b/src/groups/meta_group.cpp new file mode 100644 index 0000000..cd1314a --- /dev/null +++ b/src/groups/meta_group.cpp @@ -0,0 +1,25 @@ +#include "meta_group.hpp" + +#include + +#include "session/config/groups/info.hpp" +#include "session/config/groups/keys.hpp" +#include "session/config/groups/members.hpp" + +namespace session::nodeapi { + +using config::groups::Info; +using config::groups::Keys; +using config::groups::Members; + +using std::make_shared; + +MetaGroup::MetaGroup( + std::shared_ptr info, + std::shared_ptr members, + std::shared_ptr ke) : + MetaBase(), info{info}, members{members}, keys{keys} {} + +explicit MetaGroup::MetaGroup(const Napi::CallbackInfo& info) {} + +} // namespace session::nodeapi diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp new file mode 100644 index 0000000..ae9ed3b --- /dev/null +++ b/src/groups/meta_group.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "../meta/meta_base.hpp" +#include "session/config/groups/info.hpp" +#include "session/config/groups/keys.hpp" +#include "session/config/groups/members.hpp" + +namespace session::nodeapi { + +class MetaGroup : public MetaBase { + public: + explicit MetaGroup( + std::shared_ptr info, + std::shared_ptr members, + std::shared_ptr keys); + + explicit MetaGroup(const Napi::CallbackInfo& info); + + bool info_needs_push() { return this->info->needs_push(); } + bool members_needs_push() { return this->members->needs_push(); } + bool keys_needs_rekey() { return this->keys->needs_rekey(); } + session::ustring_view keys_rekey() { return this->keys->rekey(*info, *members); } + + private: + std::shared_ptr info; + std::shared_ptr members; + std::shared_ptr keys; +}; + +} // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp new file mode 100644 index 0000000..ce55d71 --- /dev/null +++ b/src/groups/meta_group_wrapper.cpp @@ -0,0 +1,26 @@ +#include "meta_group_wrapper.hpp" + +#include + +#include + +namespace session::nodeapi { + +void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { + NoBaseClassInitHelper( + env, + exports, + "MetaGroupWrapperNode", + { + InstanceMethod("infoNeedsPush", &MetaGroupWrapper::infoNeedsPush), + InstanceMethod("membersNeedsPush", &MetaGroupWrapper::membersNeedsPush), + InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), + }); +} + +MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : + MetaBaseWrapper{}, + Napi::ObjectWrap{info}, + meta_group{constructGroupWrapper(info, "MetaGroupWrapper")} {} + +} // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp new file mode 100644 index 0000000..e26ceeb --- /dev/null +++ b/src/groups/meta_group_wrapper.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include "../meta/meta_base_wrapper.hpp" +#include "../utilities.hpp" +#include "./meta_group.hpp" + +namespace session::nodeapi { +using session::nodeapi::MetaGroup; + +class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap { + public: + static void Init(Napi::Env env, Napi::Object exports); + + explicit MetaGroupWrapper(const Napi::CallbackInfo& info); + + private: + std::shared_ptr meta_group; + + /** Info Actions */ + + Napi::Value infoNeedsPush(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + return meta_group->info_needs_push(); + }); + } + + /** Members Actions */ + + Napi::Value membersNeedsPush(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->members_needs_push(); }); + } + + /** Keys Actions */ + + Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys_needs_rekey(); }); + } + + Napi::Value keyRekey(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys_rekey(); }); + } +}; + +} // namespace session::nodeapi diff --git a/src/meta/meta_base.cpp b/src/meta/meta_base.cpp new file mode 100644 index 0000000..3296e16 --- /dev/null +++ b/src/meta/meta_base.cpp @@ -0,0 +1,11 @@ +#include "meta_base.hpp" + +#include + +#include "session/types.hpp" + +namespace session::nodeapi { + +MetaBase::MetaBase() {} + +} // namespace session::nodeapi diff --git a/src/meta/meta_base.hpp b/src/meta/meta_base.hpp new file mode 100644 index 0000000..4ae1d33 --- /dev/null +++ b/src/meta/meta_base.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include "../base_config.hpp" + +namespace session::nodeapi { + +class MetaBase { + + public: + explicit MetaBase(); +}; + +} // namespace session::nodeapi diff --git a/src/meta/meta_base_wrapper.cpp b/src/meta/meta_base_wrapper.cpp new file mode 100644 index 0000000..97f9f02 --- /dev/null +++ b/src/meta/meta_base_wrapper.cpp @@ -0,0 +1,3 @@ +#include + +#include "base_config.hpp" diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp new file mode 100644 index 0000000..9749b45 --- /dev/null +++ b/src/meta/meta_base_wrapper.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include + +#include "../base_config.hpp" +#include "../groups/meta_group.hpp" + +namespace session::nodeapi { + +class MetaBaseWrapper { + + public: + explicit MetaBaseWrapper(); + + virtual ~MetaBaseWrapper() = default; + + template , int> = 0> + static void NoBaseClassInitHelper( + Napi::Env env, + Napi::Object exports, + const char* class_name, + std::vector properties) { + + // not adding the baseMethods here from withBaseMethods() + Napi::Function cls = T::DefineClass(env, class_name, std::move(properties)); + + auto ref = std::make_unique(); + *ref = Napi::Persistent(cls); + env.SetInstanceData(ref.release()); + + exports.Set(class_name, cls); + } + + static std::shared_ptr constructGroupWrapper( + const Napi::CallbackInfo& info, const std::string& class_name) { + return wrapExceptions(info, [&] { + if (!info.IsConstructCall()) + throw std::invalid_argument{ + "You need to call the constructor with the `new` syntax"}; + + assertInfoLength(info, 1); + auto arg = info[0]; + assertIsObject(arg); + auto obj = arg.As(); + + if (obj.IsEmpty()) + throw std::invalid_argument("constructGroupWrapper received empty"); + + assertIsUInt8Array(obj.Get("userEd25519Secretkey")); + auto user_ed25519_secretkey = toCppBuffer( + obj.Get("userEd25519Secretkey"), + class_name + ":constructGroupWrapper.userEd25519Secretkey"); + + assertIsUInt8Array(obj.Get("groupEd25519Pubkey")); + auto group_ed25519_pubkey = toCppBuffer( + obj.Get("groupEd25519Pubkey"), + class_name + ":constructGroupWrapper.groupEd25519Pubkey"); + + std::optional group_ed25519_secretkey = maybeNonemptyBuffer( + obj.Get("groupEd25519Secretkey"), + class_name + ":constructGroupWrapper.groupEd25519Secretkey"); + + std::optional dumped_info = maybeNonemptyBuffer( + obj.Get("dumpedInfo"), class_name + ":constructGroupWrapper.dumpedInfo"); + std::optional dumped_members = maybeNonemptyBuffer( + obj.Get("dumpedMembers"), class_name + ":constructGroupWrapper.dumpedMembers"); + std::optional dumped_keys = maybeNonemptyBuffer( + obj.Get("dumpedKeys"), class_name + ":constructGroupWrapper.dumpedKeys"); + + auto info = std::make_shared( + group_ed25519_pubkey, group_ed25519_secretkey, dumped_info); + + auto members = std::make_shared( + group_ed25519_pubkey, group_ed25519_secretkey, dumped_members); + + auto keys = std::make_shared( + user_ed25519_secretkey, + group_ed25519_pubkey, + group_ed25519_secretkey, + dumped_keys, + *info, + *members); + + return std::make_shared(info, members, keys); + }); + } +}; + +} // namespace session::nodeapi diff --git a/groups/groupinfo.d.ts b/types/groups/groupinfo.d.ts similarity index 100% rename from groups/groupinfo.d.ts rename to types/groups/groupinfo.d.ts diff --git a/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts similarity index 100% rename from groups/groupmembers.d.ts rename to types/groups/groupmembers.d.ts diff --git a/groups/index.d.ts b/types/groups/index.d.ts similarity index 67% rename from groups/index.d.ts rename to types/groups/index.d.ts index a11ef9b..51779d4 100644 --- a/groups/index.d.ts +++ b/types/groups/index.d.ts @@ -1,2 +1,3 @@ /// /// +/// diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts new file mode 100644 index 0000000..3a65495 --- /dev/null +++ b/types/groups/metagroup.d.ts @@ -0,0 +1,48 @@ +/// + +declare module 'libsession_util_nodejs' { + type ConstructorOptions = { + userEd25519Secretkey: Uint8Array; + groupEd25519Pubkey: Uint8Array; + groupEd25519Secretkey: Uint8Array | null; + dumpedInfo: Uint8Array | null; + dumpedMembers: Uint8Array | null; + dumpedKeys: Uint8Array | null; + }; + + type MetaGroupWrapper = { + init: (options: ConstructorOptions) => void; + + // info + infoNeedsPush: () => boolean; + + // members + membersNeedsPush: () => boolean; + + // keys + keysNeedsRekey: () => boolean; + }; + + export type MetaGroupWrapperActionsCalls = MakeWrapperActionCalls; + + export class MetaGroupWrapperNode { + constructor(ConstructorOptions); + // members + + public infoNeedsPush: MetaGroupWrapper['infoNeedsPush']; + + // members + + public membersNeedsPush: MetaGroupWrapper['membersNeedsPush']; + + // keys + + public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; + } + + export type MetaGroupActionsType = + | ['init', ConstructorOptions] + | MakeActionCall + | MakeActionCall + | MakeActionCall; +} diff --git a/shared.d.ts b/types/shared.d.ts similarity index 92% rename from shared.d.ts rename to types/shared.d.ts index 2117317..b898329 100644 --- a/shared.d.ts +++ b/types/shared.d.ts @@ -3,7 +3,9 @@ declare module 'libsession_util_nodejs' { ...args: Parameters ) => Promise>; - type MakeWrapperActionCalls = { + export type RecordOfFunctions = Record any>; + + type MakeWrapperActionCalls = { [Property in keyof Type]: AsyncWrapper; }; @@ -14,7 +16,7 @@ declare module 'libsession_util_nodejs' { export type PushConfigResult = { data: Uint8Array; seqno: number; hashes: Array }; - type MakeActionCall = [B, ...Parameters]; + type MakeActionCall = [B, ...Parameters]; /** * @@ -84,7 +86,7 @@ declare module 'libsession_util_nodejs' { ...args: Parameters ) => Promise>; - type MakeGroupWrapperActionCalls = { + type MakeGroupWrapperActionCalls = { [Property in keyof Omit]: AsyncGroupWrapper; }; diff --git a/user/contacts.d.ts b/types/user/contacts.d.ts similarity index 97% rename from user/contacts.d.ts rename to types/user/contacts.d.ts index fb107a0..0db43cf 100644 --- a/user/contacts.d.ts +++ b/types/user/contacts.d.ts @@ -1,3 +1,5 @@ +/// + /** * * Contacts wrapper logic diff --git a/user/convovolatile.d.ts b/types/user/convovolatile.d.ts similarity index 98% rename from user/convovolatile.d.ts rename to types/user/convovolatile.d.ts index fca4fea..e7756eb 100644 --- a/user/convovolatile.d.ts +++ b/types/user/convovolatile.d.ts @@ -1,3 +1,5 @@ +/// + declare module 'libsession_util_nodejs' { export type ConvoVolatileType = '1o1' | UserGroupsType; diff --git a/user/index.d.ts b/types/user/index.d.ts similarity index 100% rename from user/index.d.ts rename to types/user/index.d.ts diff --git a/user/userconfig.d.ts b/types/user/userconfig.d.ts similarity index 97% rename from user/userconfig.d.ts rename to types/user/userconfig.d.ts index 95fedd5..1ec35fa 100644 --- a/user/userconfig.d.ts +++ b/types/user/userconfig.d.ts @@ -1,3 +1,5 @@ +/// + declare module 'libsession_util_nodejs' { /** * diff --git a/user/usergroups.d.ts b/types/user/usergroups.d.ts similarity index 100% rename from user/usergroups.d.ts rename to types/user/usergroups.d.ts From 14495a325bc18b9548f7384b8fec0dc10fc65cd9 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 4 Sep 2023 13:24:25 +1000 Subject: [PATCH 06/64] feat: add start of metagroup wrapper+js bindings --- libsession-util | 2 +- src/base_config.hpp | 5 +- src/contacts_config.cpp | 2 +- src/groups/group_info_config.cpp | 100 --------------- src/groups/group_info_config.hpp | 25 ---- src/groups/group_members_config.cpp | 186 ---------------------------- src/groups/group_members_config.hpp | 35 ------ src/groups/meta_group.hpp | 121 ++++++++++++++++-- src/groups/meta_group_wrapper.cpp | 68 ++++++++-- src/groups/meta_group_wrapper.hpp | 182 ++++++++++++++++++++++++++- src/profile_pic.cpp | 12 -- src/profile_pic.hpp | 25 +++- src/user_config.cpp | 2 +- src/utilities.hpp | 1 + types/groups/groupinfo.d.ts | 44 +------ types/groups/groupmembers.d.ts | 34 ++--- types/groups/index.d.ts | 1 - types/groups/metagroup.d.ts | 62 +++++++--- 18 files changed, 434 insertions(+), 473 deletions(-) delete mode 100644 src/groups/group_info_config.cpp delete mode 100644 src/groups/group_info_config.hpp delete mode 100644 src/groups/group_members_config.cpp delete mode 100644 src/groups/group_members_config.hpp diff --git a/libsession-util b/libsession-util index 8837103..517a61a 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 883710340a14b74ffbac482b8b4b41aadcad446e +Subproject commit 517a61a455d31cd9363198d1b3d02f20093a5811 diff --git a/src/base_config.hpp b/src/base_config.hpp index 627b14b..27a233c 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -12,12 +12,13 @@ #include "session/types.hpp" #include "utilities.hpp" +using ustring_view = std::basic_string_view; + namespace session::nodeapi { class ConfigBaseImpl; template -inline constexpr bool is_derived_napi_wrapper = - std::is_base_of_v&& std::is_base_of_v, T>; +inline constexpr bool is_derived_napi_wrapper = std::is_base_of_v, T>; /// Base implementation class for config types; this provides the napi wrappers for the base /// methods. Subclasses should inherit from this (alongside Napi::ObjectWrap) diff --git a/src/contacts_config.cpp b/src/contacts_config.cpp index 712cc0b..2936336 100644 --- a/src/contacts_config.cpp +++ b/src/contacts_config.cpp @@ -49,7 +49,7 @@ struct toJs_impl { obj["createdAtSeconds"] = toJs(env, contact.created); // obj["expirationMode"] = toJs(env, expiration_mode_string(contact.exp_mode)); // obj["expirationTimerSeconds"] = toJs(env, contact.exp_timer.count()); - obj["profilePicture"] = object_from_profile_pic(env, contact.profile_picture); + obj["profilePicture"] = toJs(env, contact.profile_picture); return obj; } diff --git a/src/groups/group_info_config.cpp b/src/groups/group_info_config.cpp deleted file mode 100644 index cca42d2..0000000 --- a/src/groups/group_info_config.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "group_info_config.hpp" - -#include - -#include "base_config.hpp" -#include "profile_pic.hpp" -#include "session/config/groups/info.hpp" -#include "session/types.hpp" - -namespace session::nodeapi { - -using config::groups::Info; - -void GroupInfoWrapper::Init(Napi::Env env, Napi::Object exports) { - InitHelper( - env, - exports, - "GroupInfoWrapperNode", - { - // group related methods - InstanceMethod("getInfo", &GroupInfoWrapper::getInfo), - InstanceMethod("setInfo", &GroupInfoWrapper::setInfo), - InstanceMethod("destroy", &GroupInfoWrapper::destroy), - - }); -} - -GroupInfoWrapper::GroupInfoWrapper(const Napi::CallbackInfo& info) : - ConfigBaseImpl{construct3Args(info, "GroupsInfo")}, - Napi::ObjectWrap{info} {} - -// /** -// * ================================================= -// * ==================== GETTERS ==================== -// * ================================================= -// */ - -Napi::Value GroupInfoWrapper::getInfo(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - auto obj = Napi::Object::New(env); - - obj["name"] = toJs(env, config.get_name()); - obj["createdAtSeconds"] = toJs(env, config.get_created()); - obj["deleteAttachBeforeSeconds"] = toJs(env, config.get_delete_attach_before()); - obj["deleteBeforeSeconds"] = toJs(env, config.get_delete_before()); - - if (auto expiry = config.get_expiry_timer(); expiry) - obj["expirySeconds"] = toJs(env, expiry->count()); - obj["isDestroyed"] = toJs(env, config.is_destroyed()); - obj["profilePicture"] = object_from_profile_pic(env, config.get_profile_pic()); - - return obj; - }); -} - -Napi::Value GroupInfoWrapper::setInfo(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - auto arg = info[0]; - assertIsObject(arg); - auto obj = arg.As(); - - if (auto name = maybeNonemptyString(obj.Get("name"), "GroupInfoWrapper::setInfo name")) - config.set_name(*name); - - if (auto created = maybeNonemptyInt( - obj.Get("createdAtSeconds"), "GroupInfoWrapper::setInfo set_created")) - config.set_created(std::move(*created)); - - if (auto expiry = maybeNonemptyInt( - obj.Get("expirySeconds"), "GroupInfoWrapper::setInfo set_expiry_timer")) - config.set_expiry_timer(std::chrono::seconds{*expiry}); - - if (auto deleteBefore = maybeNonemptyInt( - obj.Get("deleteBeforeSeconds"), "GroupInfoWrapper::setInfo set_delete_before")) - config.set_delete_before(std::move(*deleteBefore)); - - if (auto deleteAttachBefore = maybeNonemptyInt( - obj.Get("deleteAttachBeforeSeconds"), - "GroupInfoWrapper::setInfo set_delete_attach_before")) - config.set_delete_attach_before(std::move(*deleteAttachBefore)); - - if (auto profilePicture = obj.Get("profilePicture")) { - auto profilePic = profile_pic_from_object(profilePicture); - config.set_profile_pic(profilePic); - } - - return this->getInfo(info); - }); -} - -Napi::Value GroupInfoWrapper::destroy(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - config.destroy_group(); - return this->getInfo(info); - }); -} - -} // namespace session::nodeapi diff --git a/src/groups/group_info_config.hpp b/src/groups/group_info_config.hpp deleted file mode 100644 index af49615..0000000 --- a/src/groups/group_info_config.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include "../base_config.hpp" -#include "session/config/groups/info.hpp" - -namespace session::nodeapi { - -class GroupInfoWrapper : public ConfigBaseImpl, public Napi::ObjectWrap { - public: - static void Init(Napi::Env env, Napi::Object exports); - - explicit GroupInfoWrapper(const Napi::CallbackInfo& info); - - private: - session::config::groups::Info& config{get_config()}; - - // GroupInfo related methods - Napi::Value getInfo(const Napi::CallbackInfo& info); - Napi::Value setInfo(const Napi::CallbackInfo& info); - Napi::Value destroy(const Napi::CallbackInfo& info); -}; - -} // namespace session::nodeapi diff --git a/src/groups/group_members_config.cpp b/src/groups/group_members_config.cpp deleted file mode 100644 index 1e5c2bb..0000000 --- a/src/groups/group_members_config.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "group_members_config.hpp" - -#include - -#include "../base_config.hpp" -#include "../profile_pic.hpp" -#include "session/config/groups/members.hpp" -#include "session/types.hpp" - -namespace session::nodeapi { - -using config::groups::Members; -using session::config::groups::member; - -template <> -struct toJs_impl { - Napi::Object operator()(const Napi::Env& env, const member& info) { - auto obj = Napi::Object::New(env); - - obj["pubkeyHex"] = toJs(env, info.session_id); - obj["name"] = toJs(env, info.name); - obj["profilePicture"] = toJs(env, info.profile_picture); - obj["invitePending"] = toJs(env, info.invite_pending()); - obj["inviteFailed"] = toJs(env, info.invite_failed()); - obj["promotionPending"] = toJs(env, info.promotion_pending()); - obj["promotionFailed"] = toJs(env, info.promotion_failed()); - obj["promoted"] = toJs(env, info.promoted()); - - return obj; - } -}; - -void GroupMembersWrapper::Init(Napi::Env env, Napi::Object exports) { - InitHelper( - env, - exports, - "GroupMembersWrapperNode", - { - // group related methods - InstanceMethod("get", &GroupMembersWrapper::get), - InstanceMethod("getOrConstruct", &GroupMembersWrapper::getOrConstruct), - InstanceMethod("getAll", &GroupMembersWrapper::getAll), - InstanceMethod("setName", &GroupMembersWrapper::setName), - InstanceMethod("setInvited", &GroupMembersWrapper::setInvited), - InstanceMethod("setAccepted", &GroupMembersWrapper::setAccepted), - InstanceMethod("setPromoted", &GroupMembersWrapper::setPromoted), - InstanceMethod("setProfilePicture", &GroupMembersWrapper::setProfilePicture), - InstanceMethod("erase", &GroupMembersWrapper::erase), - - }); -} - -GroupMembersWrapper::GroupMembersWrapper(const Napi::CallbackInfo& info) : - ConfigBaseImpl{construct3Args(info, "GroupsMembers")}, - Napi::ObjectWrap{info} {} - -/** - * ================================================= - * ==================== GETTERS ==================== - * ================================================= - */ - -Napi::Value GroupMembersWrapper::get(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::get"); - - return config.get(pubkeyHex); - }); -} - -Napi::Value GroupMembersWrapper::getOrConstruct(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::getOrConstruct"); - - return config.get_or_construct(pubkeyHex); - }); -} - -Napi::Value GroupMembersWrapper::getAll(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - assertInfoLength(info, 0); - - std::vector allMembers; - for (auto& member : config) { - allMembers.push_back(member); - } - - return allMembers; - }); -} - -Napi::Value GroupMembersWrapper::setName(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsString(info[0]); - assertIsString(info[1]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setName1"); - auto newName = toCppString(info[1], "GroupMembersWrapper::setName2"); - auto m = config.get_or_construct(pubkeyHex); - m.set_name(newName); - - return m; - }); -} - -Napi::Value GroupMembersWrapper::setInvited(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsString(info[0]); - assertIsBoolean(info[1]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setInvited1"); - auto failed = toCppBoolean(info[1], "GroupMembersWrapper::setInvited2"); - auto m = config.get_or_construct(pubkeyHex); - m.set_invited(failed); - - return m; - }); -} - -Napi::Value GroupMembersWrapper::setAccepted(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setAccepted"); - auto m = config.get_or_construct(pubkeyHex); - m.set_accepted(); - - return m; - }); -} - -Napi::Value GroupMembersWrapper::setPromoted(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsString(info[0]); - assertIsBoolean(info[1]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setPromoted1"); - auto failed = toCppBoolean(info[1], "GroupMembersWrapper::setPromoted2"); - auto m = config.get_or_construct(pubkeyHex); - m.set_promoted(failed); - - return m; - }); -} - -Napi::Value GroupMembersWrapper::setProfilePicture(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsString(info[0]); - assertIsObject(info[1]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::setAccepted"); - auto profilePicture = profile_pic_from_object(info[1]); - - auto m = config.get_or_construct(pubkeyHex); - m.profile_picture = profilePicture; - config.set(m); - - return m; - }); -} - -Napi::Value GroupMembersWrapper::erase(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], "GroupMembersWrapper::erase"); - return config.erase(pubkeyHex); - }); -} - -} // namespace session::nodeapi diff --git a/src/groups/group_members_config.hpp b/src/groups/group_members_config.hpp deleted file mode 100644 index 6ca6aab..0000000 --- a/src/groups/group_members_config.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -#include "../base_config.hpp" -#include "session/config/groups/members.hpp" - -namespace session::nodeapi { - -class GroupMembersWrapper : public ConfigBaseImpl, public Napi::ObjectWrap { - public: - static void Init(Napi::Env env, Napi::Object exports); - - explicit GroupMembersWrapper(const Napi::CallbackInfo& info); - - private: - session::config::groups::Members& config{get_config()}; - - // GroupMembers related methods - Napi::Value get(const Napi::CallbackInfo& info); - Napi::Value getOrConstruct(const Napi::CallbackInfo& info); - Napi::Value getAll(const Napi::CallbackInfo& info); - - // setters - Napi::Value setName(const Napi::CallbackInfo& info); - Napi::Value setInvited(const Napi::CallbackInfo& info); - Napi::Value setAccepted(const Napi::CallbackInfo& info); - Napi::Value setPromoted(const Napi::CallbackInfo& info); - Napi::Value setProfilePicture(const Napi::CallbackInfo& info); - - // eraser - Napi::Value erase(const Napi::CallbackInfo& info); -}; - -} // namespace session::nodeapi diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index ae9ed3b..6c636f9 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -9,19 +9,126 @@ namespace session::nodeapi { +using config::groups::Info; +using config::groups::Keys; +using config::groups::Members; +using session::config::profile_pic; +using std::pair; +using std::string; +using std::tuple; +using std::vector; + class MetaGroup : public MetaBase { public: explicit MetaGroup( - std::shared_ptr info, - std::shared_ptr members, - std::shared_ptr keys); + std::shared_ptr info, + std::shared_ptr members, + std::shared_ptr keys); explicit MetaGroup(const Napi::CallbackInfo& info); - bool info_needs_push() { return this->info->needs_push(); } - bool members_needs_push() { return this->members->needs_push(); } - bool keys_needs_rekey() { return this->keys->needs_rekey(); } - session::ustring_view keys_rekey() { return this->keys->rekey(*info, *members); } + // + // + // + // + // + // shared actions + + auto needs_push() { return this->members->needs_push() || this->info->needs_push(); } + + auto push() { + vector>>> to_push; + if (this->members->needs_push()) { + to_push.push_back(std::make_pair("GroupMember"s, this->members->push())); + } + + if (this->info->needs_push()) { + to_push.push_back(std::make_pair("GroupInfo"s, this->info->push())); + } + + if (this->keys->needs_rekey()) { + to_push.push_back(std::make_pair("GroupKeys"s, this->info->push())); + } + return to_push; + } + + // + // + // + // + // + // info wrapper actions + + auto info_subaccount_mask() { return this->info->subaccount_mask(); } + auto info_get_name() { return this->info->get_name(); } + auto info_set_name(std::string_view new_name) { return this->info->set_name(new_name); } + + auto info_get_profile_pic() { return this->info->get_profile_pic(); } + auto info_set_profile_pic(profile_pic pic) { return this->info->set_profile_pic(pic); } + + auto info_set_expiry_timer(std::chrono::seconds expiration_timer) { + return this->info->set_expiry_timer(expiration_timer); + } + auto info_get_expiry_timer() { return this->info->get_expiry_timer(); } + + auto info_set_created(int64_t timestamp) { return this->info->set_created(timestamp); } + auto info_get_created() { return this->info->get_created(); } + + auto info_set_delete_before(int64_t timestamp) { + return this->info->set_delete_before(timestamp); + } + auto info_get_delete_before() { return this->info->get_delete_before(); } + + auto info_set_delete_attach_before(int64_t timestamp) { + return this->info->set_delete_attach_before(timestamp); + } + auto info_get_delete_attach_before() { return this->info->get_delete_attach_before(); } + + auto info_destroy_group() { return this->info->destroy_group(); } + auto info_is_destroyed() { return this->info->is_destroyed(); } + + // + // + // + // + // member wrapper actions + auto member_get(std::string_view pubkey_hex) { return this->members->get(pubkey_hex); } + auto member_get_or_construct(std::string_view pubkey_hex) { + return this->members->get_or_construct(pubkey_hex); + } + + auto member_get_all() { + std::vector allMembers; + for (auto& member : *this->members) { + allMembers.push_back(member); + } + return allMembers; + } + + auto member_set(const session::config::groups::member& member) { + this->members->set(member); + return this->members->get_or_construct(member.session_id); + } + + auto member_erase(std::string_view session_id) { return this->members->erase(session_id); } + + // + // + // + // + // keys wrapper actions + auto keys_admin() { return this->keys->admin(); } + auto keys_key_supplement(std::vector sids) const; + auto keys_rekey() { return this->keys->rekey(*info, *members); } + auto keys_needs_rekey() { return this->keys->needs_rekey(); } + auto keys_needs_dump() { return this->keys->needs_dump(); } + auto keys_pending_config() { return this->keys->pending_config(); } + auto keys_encrypt_message(ustring_view plaintext, bool compress = true) const { + return this->keys->encrypt_message(plaintext, compress); + } + auto keys_decrypt_message(ustring_view ciphertext) const { + return this->keys->decrypt_message(ciphertext); + } private: std::shared_ptr info; diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index ce55d71..a491041 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -6,21 +6,65 @@ namespace session::nodeapi { -void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { - NoBaseClassInitHelper( - env, - exports, - "MetaGroupWrapperNode", - { - InstanceMethod("infoNeedsPush", &MetaGroupWrapper::infoNeedsPush), - InstanceMethod("membersNeedsPush", &MetaGroupWrapper::membersNeedsPush), - InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), - }); -} - MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : MetaBaseWrapper{}, Napi::ObjectWrap{info}, meta_group{constructGroupWrapper(info, "MetaGroupWrapper")} {} +// Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { +// return wrapResult(info, [&] { +// auto env = info.Env(); +// auto obj = Napi::Object::New(env); + +// obj["name"] = toJs(env, config.get_name()); +// obj["createdAtSeconds"] = toJs(env, config.get_created()); +// obj["deleteAttachBeforeSeconds"] = toJs(env, config.get_delete_attach_before()); +// obj["deleteBeforeSeconds"] = toJs(env, config.get_delete_before()); + +// if (auto expiry = config.get_expiry_timer(); expiry) +// obj["expirySeconds"] = toJs(env, expiry->count()); +// obj["isDestroyed"] = toJs(env, config.is_destroyed()); +// obj["profilePicture"] = toJs(env, config.get_profile_pic()); + +// return obj; +// }); +// } + +// Napi::Value MetaGroupWrapper::infoSet(const Napi::CallbackInfo& info) { +// return wrapResult(info, [&] { +// assertInfoLength(info, 1); +// auto arg = info[0]; +// assertIsObject(arg); +// auto obj = arg.As(); + +// if (auto name = maybeNonemptyString(obj.Get("name"), "MetaGroupWrapper::setInfo name")) +// config.set_name(*name); + +// if (auto created = maybeNonemptyInt( +// obj.Get("createdAtSeconds"), "MetaGroupWrapper::setInfo set_created")) +// config.set_created(std::move(*created)); + +// if (auto expiry = maybeNonemptyInt( +// obj.Get("expirySeconds"), "MetaGroupWrapper::setInfo set_expiry_timer")) +// config.set_expiry_timer(std::chrono::seconds{*expiry}); + +// if (auto deleteBefore = maybeNonemptyInt( +// obj.Get("deleteBeforeSeconds"), "MetaGroupWrapper::setInfo +// set_delete_before")) +// config.set_delete_before(std::move(*deleteBefore)); + +// if (auto deleteAttachBefore = maybeNonemptyInt( +// obj.Get("deleteAttachBeforeSeconds"), +// "MetaGroupWrapper::setInfo set_delete_attach_before")) +// config.set_delete_attach_before(std::move(*deleteAttachBefore)); + +// if (auto profilePicture = obj.Get("profilePicture")) { +// auto profilePic = profile_pic_from_object(profilePicture); +// config.set_profile_pic(profilePic); +// } + +// return this->getInfo(info); +// }); +// } + } // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index e26ceeb..0fee26c 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -3,34 +3,204 @@ #include #include "../meta/meta_base_wrapper.hpp" +#include "../profile_pic.hpp" #include "../utilities.hpp" #include "./meta_group.hpp" namespace session::nodeapi { +using config::groups::Members; +using session::config::groups::member; using session::nodeapi::MetaGroup; +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const member& info) { + auto obj = Napi::Object::New(env); + + obj["pubkeyHex"] = toJs(env, info.session_id); + obj["name"] = toJs(env, info.name); + obj["profilePicture"] = toJs(env, info.profile_picture); + obj["invitePending"] = toJs(env, info.invite_pending()); + obj["inviteFailed"] = toJs(env, info.invite_failed()); + obj["promotionPending"] = toJs(env, info.promotion_pending()); + obj["promotionFailed"] = toJs(env, info.promotion_failed()); + obj["promoted"] = toJs(env, info.promoted()); + + return obj; + } +}; + class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap { public: - static void Init(Napi::Env env, Napi::Object exports); + static void Init(Napi::Env env, Napi::Object exports) { + NoBaseClassInitHelper( + env, + exports, + "MetaGroupWrapperNode", + { + // shared exposed functions + InstanceMethod("needsPush", &MetaGroupWrapper::needsPush), + + // infos exposed functions + // InstanceMethod("infoGet", &MetaGroupWrapper::infoGet), + // InstanceMethod("infoSet", &MetaGroupWrapper::infoSet), + // InstanceMethod("infoDestroy", &MetaGroupWrapper::infoDestroy), + + // members exposed functions + InstanceMethod("memberGet", &MetaGroupWrapper::memberGet), + InstanceMethod( + "memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), + InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), + InstanceMethod("memberSetName", &MetaGroupWrapper::memberSetName), + InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), + InstanceMethod("memberSetAccepted", &MetaGroupWrapper::memberSetAccepted), + InstanceMethod("memberSetPromoted", &MetaGroupWrapper::memberSetPromoted), + InstanceMethod( + "memberSetProfilePicture", + &MetaGroupWrapper::memberSetProfilePicture), + InstanceMethod("memberErase", &MetaGroupWrapper::memberErase), + + // keys exposed functions + InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), + }); + } explicit MetaGroupWrapper(const Napi::CallbackInfo& info); private: std::shared_ptr meta_group; + /* Shared Actions */ + + Napi::Value needsPush(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->needs_push(); }); + } + /** Info Actions */ - Napi::Value infoNeedsPush(const Napi::CallbackInfo& info) { + // Napi::Value infoGet(const Napi::CallbackInfo& info); + + // Napi::Value infoSet(const Napi::CallbackInfo& info); + + // Napi::Value infoDestroy(const Napi::CallbackInfo& info) { + // return wrapResult(info, [&] { + // meta_group->destroy_group(); + // return meta_group->info_get(info); + // }); + // } + + /** Members Actions */ + + Napi::Value memberGetAll(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->member_get_all(); }); + } + + Napi::Value memberGet(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { auto env = info.Env(); - return meta_group->info_needs_push(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + return meta_group->member_get(pubkeyHex); }); } - /** Members Actions */ + Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + return meta_group->member_get_or_construct(pubkeyHex); + }); + } + + Napi::Value memberSetName(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsString(info[1]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto newName = toCppString(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->member_get_or_construct(pubkeyHex); + m.set_name(newName); + return this->meta_group->member_set(m); + }); + } + + Napi::Value memberSetInvited(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsBoolean(info[1]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->member_get_or_construct(pubkeyHex); + m.set_invited(failed); + return this->meta_group->member_set(m); + }); + } + + Napi::Value memberSetAccepted(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto m = this->meta_group->member_get_or_construct(pubkeyHex); + m.set_accepted(); + + return this->meta_group->member_set(m); + }); + } + + Napi::Value memberSetPromoted(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsBoolean(info[1]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->member_get_or_construct(pubkeyHex); + m.set_promoted(failed); + + return this->meta_group->member_set(m); + }); + } + + Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsObject(info[1]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto profilePicture = profile_pic_from_object(info[1]); - Napi::Value membersNeedsPush(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->members_needs_push(); }); + auto m = this->meta_group->member_get_or_construct(pubkeyHex); + m.profile_picture = profilePicture; + return this->meta_group->member_set(m); + }); + } + + Napi::Value memberErase(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + std::optional result; + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto erased = this->meta_group->member_erase(pubkeyHex); + if (erased) { + meta_group->keys_rekey(); + } + + return erased; + }); } /** Keys Actions */ diff --git a/src/profile_pic.cpp b/src/profile_pic.cpp index e513112..02a55d5 100644 --- a/src/profile_pic.cpp +++ b/src/profile_pic.cpp @@ -5,18 +5,6 @@ namespace session::nodeapi { -Napi::Object object_from_profile_pic(const Napi::Env& env, const config::profile_pic& pic) { - auto obj = Napi::Object::New(env); - if (pic) { - obj["url"] = toJs(env, pic.url); - obj["key"] = toJs(env, pic.key); - } else { - obj["url"] = env.Null(); - obj["key"] = env.Null(); - } - return obj; -} - config::profile_pic profile_pic_from_object(Napi::Value val) { if (val.IsNull() || val.IsUndefined()) return {}; diff --git a/src/profile_pic.hpp b/src/profile_pic.hpp index d6c3aed..c959571 100644 --- a/src/profile_pic.hpp +++ b/src/profile_pic.hpp @@ -1,16 +1,31 @@ #include #include "session/config/profile_pic.hpp" +#include "utilities.hpp" namespace session::nodeapi { // Returns {"url": "...", "key": buffer} object; both values will be Null if the pic is not set. -Napi::Object object_from_profile_pic(const Napi::Env& env, const config::profile_pic& pic); -// Constructs a profile_pic from a Napi::Value which must be either Null or an Object; if an Object -// then it *must* contain "url" (string or null) and "key" (uint8array of size 32 or null) keys; if -// either is empty or Null then you get back an empty (i.e. clearing) profile_pic. Throws on -// invalid input. +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const config::profile_pic& pic) { + auto obj = Napi::Object::New(env); + if (pic) { + obj["url"] = toJs(env, pic.url); + obj["key"] = toJs(env, pic.key); + } else { + obj["url"] = env.Null(); + obj["key"] = env.Null(); + } + return obj; + } +}; + +// Constructs a profile_pic from a Napi::Value which must be either Null or an Object; if an +// Object then it *must* contain "url" (string or null) and "key" (uint8array of size 32 or +// null) keys; if either is empty or Null then you get back an empty (i.e. clearing) +// profile_pic. Throws on invalid input. config::profile_pic profile_pic_from_object(Napi::Value val); } // namespace session::nodeapi diff --git a/src/user_config.cpp b/src/user_config.cpp index 92477a5..ce2ff7b 100644 --- a/src/user_config.cpp +++ b/src/user_config.cpp @@ -47,7 +47,7 @@ Napi::Value UserConfigWrapper::getUserInfo(const Napi::CallbackInfo& info) { // user_info_obj["expirySeconds"] = env.Null(); // } - auto profile_pic_obj = object_from_profile_pic(env, config.get_profile_pic()); + auto profile_pic_obj = toJs(env, config.get_profile_pic()); if (profile_pic_obj) { user_info_obj["url"] = profile_pic_obj.Get("url"); user_info_obj["key"] = profile_pic_obj.Get("key"); diff --git a/src/utilities.hpp b/src/utilities.hpp index 654a263..bc0833b 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -8,6 +8,7 @@ #include #include "session/types.hpp" +#include "utilities.hpp" namespace session::nodeapi { diff --git a/types/groups/groupinfo.d.ts b/types/groups/groupinfo.d.ts index a19b338..820f86a 100644 --- a/types/groups/groupinfo.d.ts +++ b/types/groups/groupinfo.d.ts @@ -7,46 +7,10 @@ declare module 'libsession_util_nodejs' { */ export type GroupInfoSet = GroupInfoShared; - type GroupInfoWrapper = BaseConfigWrapper & { - initGroup: ( - ed25519Pubkey: Uint8Array, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => void; - + export type GroupInfoWrapper = { // GroupInfo related methods - getInfo: () => GroupInfoGet | null; - setInfo: (info: GroupInfoSet) => GroupInfoGet; - destroy: () => void; - }; - - export type GroupInfoWrapperActionsCalls = MakeGroupWrapperActionCalls & { - initGroup: ( - ed25519Pubkey: GroupPubkeyType, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => Promise; + infoGet: () => GroupInfoGet | null; + infoSet: (info: GroupInfoSet) => GroupInfoGet; + infoDestroy: () => void; }; - - export class GroupInfoWrapperNode extends BaseConfigWrapperNode { - constructor( - ed25519Pubkey: GroupPubkeyType, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ); - - // GroupInfo related methods - public getInfo: GroupInfoWrapper['getInfo']; - public setInfo: GroupInfoWrapper['setInfo']; - public destroy: GroupInfoWrapper['destroy']; - } - - type GroupActionMap = Omit< - { [K in keyof T]: MakeGroupActionCall }, - BaseConfigFunctions - >; - - type GroupActionUnion = GroupActionMap[keyof GroupActionMap]; - - export type GroupInfoActionsType = GroupActionUnion; } diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 2219ca5..68ca217 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -20,34 +20,20 @@ declare module 'libsession_util_nodejs' { promoted: boolean; }; - type GroupMemberWrapper = BaseConfigWrapper & { - initGroup: ( - ed25519Pubkey: Uint8Array, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => void; - + type GroupMemberWrapper = { // GroupMember related methods - get: (pubkeyHex: string) => GroupMemberGet | null; - getOrConstruct: (pubkeyHex: string) => GroupMemberGet; - getAll: () => Array; + memberGet: (pubkeyHex: string) => GroupMemberGet | null; + memberGetOrConstruct: (pubkeyHex: string) => GroupMemberGet; + memberGetAll: () => Array; // setters - setName: (pubkeyHex: string, newName: string) => GroupMemberGet; - setInvited: (pubkeyHex: string, failed: boolean) => GroupMemberGet; - setPromoted: (pubkeyHex: string, failed: boolean) => GroupMemberGet; - setAccepted: (pubkeyHex: string) => GroupMemberGet; - setProfilePicture: (pubkeyHex: string, profilePicture: ProfilePicture) => GroupMemberGet; + memberSetName: (pubkeyHex: string, newName: string) => GroupMemberGet; + memberSetInvited: (pubkeyHex: string, failed: boolean) => GroupMemberGet; + memberSetPromoted: (pubkeyHex: string, failed: boolean) => GroupMemberGet; + memberSetAccepted: (pubkeyHex: string) => GroupMemberGet; + memberSetProfilePicture: (pubkeyHex: string, profilePicture: ProfilePicture) => GroupMemberGet; // eraser - erase: (pubkeyHex: string) => null; - }; - - export type GroupMemberWrapperActionsCalls = MakeGroupWrapperActionCalls & { - initGroup: ( - ed25519Pubkey: GroupPubkeyType, - secretKey: Uint8Array | null, - dump: Uint8Array | null - ) => Promise; + memberErase: (pubkeyHex: string) => null; }; } diff --git a/types/groups/index.d.ts b/types/groups/index.d.ts index 51779d4..818192a 100644 --- a/types/groups/index.d.ts +++ b/types/groups/index.d.ts @@ -1,3 +1,2 @@ /// -/// /// diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 3a65495..32adff0 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -1,4 +1,6 @@ /// +/// +/// declare module 'libsession_util_nodejs' { type ConstructorOptions = { @@ -10,30 +12,43 @@ declare module 'libsession_util_nodejs' { dumpedKeys: Uint8Array | null; }; - type MetaGroupWrapper = { - init: (options: ConstructorOptions) => void; + type MetaGroupWrapper = GroupInfoWrapper & + GroupMemberWrapper & { + init: (options: ConstructorOptions) => void; - // info - infoNeedsPush: () => boolean; + // shared actions + needsPush: () => boolean; - // members - membersNeedsPush: () => boolean; + // info - // keys - keysNeedsRekey: () => boolean; - }; + // members + + // keys + keysNeedsRekey: () => boolean; + }; export type MetaGroupWrapperActionsCalls = MakeWrapperActionCalls; export class MetaGroupWrapperNode { constructor(ConstructorOptions); - // members - public infoNeedsPush: MetaGroupWrapper['infoNeedsPush']; + // shared actions + public needsPush: MetaGroupWrapper['needsPush']; - // members + // info + public infoGet: MetaGroupWrapper['infoGet']; + public infoSet: MetaGroupWrapper['infoSet']; + public infoDestroy: MetaGroupWrapper['infoDestroy']; - public membersNeedsPush: MetaGroupWrapper['membersNeedsPush']; + // members + public memberGet: MetaGroupWrapper['memberGet']; + public memberGetOrConstruct: MetaGroupWrapper['memberGetOrConstruct']; + public memberGetAll: MetaGroupWrapper['memberGetAll']; + public memberSetAccepted: MetaGroupWrapper['memberSetAccepted']; + public memberSetName: MetaGroupWrapper['memberSetName']; + public memberSetPromoted: MetaGroupWrapper['memberSetPromoted']; + public memberSetInvited: MetaGroupWrapper['memberSetInvited']; + public memberErase: MetaGroupWrapper['memberErase']; // keys @@ -42,7 +57,24 @@ declare module 'libsession_util_nodejs' { export type MetaGroupActionsType = | ['init', ConstructorOptions] - | MakeActionCall - | MakeActionCall + // shared actions + | MakeActionCall + + // info actions + | MakeActionCall + | MakeActionCall + | MakeActionCall + + // member actions + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + + // keys actions | MakeActionCall; } From 786e669f6a4e9c9bb83c17ec271f80e3a9c1ee89 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 5 Sep 2023 14:13:04 +1000 Subject: [PATCH 07/64] feat: add meta_group wrapper functions exported to JS --- src/groups/group_keys_config.cpp | 98 ------------- src/groups/group_keys_config.hpp | 34 ----- src/groups/meta_group.cpp | 25 ---- src/groups/meta_group.hpp | 124 ++--------------- src/groups/meta_group_wrapper.cpp | 110 +++++++-------- src/groups/meta_group_wrapper.hpp | 221 +++++++++++++++++++++++++----- src/user_groups_config.cpp | 1 - src/utilities.hpp | 12 ++ types/groups/groupkeys.d.ts | 17 +++ types/groups/metagroup.d.ts | 54 ++++++-- types/user/usergroups.d.ts | 1 - 11 files changed, 325 insertions(+), 372 deletions(-) delete mode 100644 src/groups/group_keys_config.cpp delete mode 100644 src/groups/group_keys_config.hpp delete mode 100644 src/groups/meta_group.cpp create mode 100644 types/groups/groupkeys.d.ts diff --git a/src/groups/group_keys_config.cpp b/src/groups/group_keys_config.cpp deleted file mode 100644 index e32ae54..0000000 --- a/src/groups/group_keys_config.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "group_keys_config.hpp" - -#include - -#include "../base_config.hpp" -#include "../profile_pic.hpp" -#include "session/config/groups/keys.hpp" -#include "session/types.hpp" - -namespace session::nodeapi { - -static InitHelper(Napi::Env env, Napi::Object exports) { - Napi::Function cls = T::DefineClass(env, class_name, WithBaseMethods(std::move(properties))); - - auto ref = std::make_unique(); - *ref = Napi::Persistent(cls); - env.SetInstanceData(ref.release()); - - exports.Set(class_name, cls); -} - -using config::groups::Keys; - -void GroupKeysWrapper::Init(Napi::Env env, Napi::Object exports) { - InitHelper( - env, - exports, - "GroupKeysWrapperNode", - { - // group related methods - InstanceMethod("get", &GroupKeysWrapper::get), - // InstanceMethod("getOrConstruct", &GroupKeysWrapper::getOrConstruct), - // InstanceMethod("getAll", &GroupKeysWrapper::getAll), - // InstanceMethod("setName", &GroupKeysWrapper::setName), - - }); -} - -GroupKeysWrapper::GroupKeysWrapper(const Napi::CallbackInfo& info) : - Napi::ObjectWrap{info} { - return wrapExceptions(info, [&] { - if (!info.IsConstructCall()) - throw std::invalid_argument{"You need to call the constructor with the `new` syntax"}; - auto class_name = "GroupKeys"s; - assertInfoLength(info, 3); - - // we should get ed25519_pubkey as string (with 03 prefix), as first arg, secret key as - // second opt arg and optional dumped as third arg - assertIsString(info[0]); - assertIsUInt8ArrayOrNull(info[1]); - assertIsUInt8ArrayOrNull(info[2]); - std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); - std::optional secret_key; - auto second = info[1]; - if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) - secret_key = toCppBufferView(second, class_name + ".new.secret"); - - std::optional dump; - auto third = info[2]; - if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) - dump = toCppBufferView(third, class_name + ".new.dump"); - - auto withoutPrefix = ed25519_pubkey_str.substr(2); - ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); - this->config = std::make_shared(ed25519_pubkey, secret_key, dump); - }); -} - -/** - * ================================================= - * ==================== GETTERS ==================== - * ================================================= - */ - -// Napi::Value GroupKeysWrapper::get(const Napi::CallbackInfo& info) { -// return wrapResult(info, [&] { -// auto env = info.Env(); -// assertInfoLength(info, 1); -// assertIsString(info[0]); - -// auto pubkeyHex = toCppString(info[0], "GroupKeysWrapper::get"); - -// return config.get(pubkeyHex); -// }); -// } - -// Napi::Value GroupKeysWrapper::getOrConstruct(const Napi::CallbackInfo& info) { -// return wrapResult(info, [&] { -// auto env = info.Env(); -// assertInfoLength(info, 1); -// assertIsString(info[0]); - -// auto pubkeyHex = toCppString(info[0], "GroupKeysWrapper::getOrConstruct"); - -// return config.get_or_construct(pubkeyHex); -// }); -// } -} // namespace session::nodeapi diff --git a/src/groups/group_keys_config.hpp b/src/groups/group_keys_config.hpp deleted file mode 100644 index d3e3e55..0000000 --- a/src/groups/group_keys_config.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include "../base_config.hpp" -#include "session/config/groups/keys.hpp" - -namespace session::nodeapi { - -class GroupKeysWrapper : public Napi::ObjectWrap { - public: - static void Init(Napi::Env env, Napi::Object exports); - - explicit GroupKeysWrapper(const Napi::CallbackInfo& info); - - private: - std::shared_ptr config; - // GroupKeys related methods - Napi::Value get(const Napi::CallbackInfo& info); - // Napi::Value getOrConstruct(const Napi::CallbackInfo& info); - // Napi::Value getAll(const Napi::CallbackInfo& info); - - // // setters - // Napi::Value setName(const Napi::CallbackInfo& info); - // Napi::Value setInvited(const Napi::CallbackInfo& info); - // Napi::Value setAccepted(const Napi::CallbackInfo& info); - // Napi::Value setPromoted(const Napi::CallbackInfo& info); - // Napi::Value setProfilePicture(const Napi::CallbackInfo& info); - - // // eraser - // Napi::Value erase(const Napi::CallbackInfo& info); -}; - -} // namespace session::nodeapi diff --git a/src/groups/meta_group.cpp b/src/groups/meta_group.cpp deleted file mode 100644 index cd1314a..0000000 --- a/src/groups/meta_group.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "meta_group.hpp" - -#include - -#include "session/config/groups/info.hpp" -#include "session/config/groups/keys.hpp" -#include "session/config/groups/members.hpp" - -namespace session::nodeapi { - -using config::groups::Info; -using config::groups::Keys; -using config::groups::Members; - -using std::make_shared; - -MetaGroup::MetaGroup( - std::shared_ptr info, - std::shared_ptr members, - std::shared_ptr ke) : - MetaBase(), info{info}, members{members}, keys{keys} {} - -explicit MetaGroup::MetaGroup(const Napi::CallbackInfo& info) {} - -} // namespace session::nodeapi diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index 6c636f9..32b127a 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -18,122 +18,22 @@ using std::string; using std::tuple; using std::vector; +using std::make_shared; +using std::shared_ptr; + class MetaGroup : public MetaBase { public: - explicit MetaGroup( - std::shared_ptr info, - std::shared_ptr members, - std::shared_ptr keys); - - explicit MetaGroup(const Napi::CallbackInfo& info); - - // - // - // - // - // - // shared actions - - auto needs_push() { return this->members->needs_push() || this->info->needs_push(); } - - auto push() { - vector>>> to_push; - if (this->members->needs_push()) { - to_push.push_back(std::make_pair("GroupMember"s, this->members->push())); - } - - if (this->info->needs_push()) { - to_push.push_back(std::make_pair("GroupInfo"s, this->info->push())); - } - - if (this->keys->needs_rekey()) { - to_push.push_back(std::make_pair("GroupKeys"s, this->info->push())); - } - return to_push; - } - - // - // - // - // - // - // info wrapper actions - - auto info_subaccount_mask() { return this->info->subaccount_mask(); } - auto info_get_name() { return this->info->get_name(); } - auto info_set_name(std::string_view new_name) { return this->info->set_name(new_name); } - - auto info_get_profile_pic() { return this->info->get_profile_pic(); } - auto info_set_profile_pic(profile_pic pic) { return this->info->set_profile_pic(pic); } - - auto info_set_expiry_timer(std::chrono::seconds expiration_timer) { - return this->info->set_expiry_timer(expiration_timer); - } - auto info_get_expiry_timer() { return this->info->get_expiry_timer(); } - - auto info_set_created(int64_t timestamp) { return this->info->set_created(timestamp); } - auto info_get_created() { return this->info->get_created(); } - - auto info_set_delete_before(int64_t timestamp) { - return this->info->set_delete_before(timestamp); - } - auto info_get_delete_before() { return this->info->get_delete_before(); } - - auto info_set_delete_attach_before(int64_t timestamp) { - return this->info->set_delete_attach_before(timestamp); - } - auto info_get_delete_attach_before() { return this->info->get_delete_attach_before(); } - - auto info_destroy_group() { return this->info->destroy_group(); } - auto info_is_destroyed() { return this->info->is_destroyed(); } - - // - // - // - // - // member wrapper actions - auto member_get(std::string_view pubkey_hex) { return this->members->get(pubkey_hex); } - auto member_get_or_construct(std::string_view pubkey_hex) { - return this->members->get_or_construct(pubkey_hex); - } - - auto member_get_all() { - std::vector allMembers; - for (auto& member : *this->members) { - allMembers.push_back(member); - } - return allMembers; - } - - auto member_set(const session::config::groups::member& member) { - this->members->set(member); - return this->members->get_or_construct(member.session_id); - } - - auto member_erase(std::string_view session_id) { return this->members->erase(session_id); } + shared_ptr info; + shared_ptr members; + shared_ptr keys; - // - // - // - // - // keys wrapper actions - auto keys_admin() { return this->keys->admin(); } - auto keys_key_supplement(std::vector sids) const; - auto keys_rekey() { return this->keys->rekey(*info, *members); } - auto keys_needs_rekey() { return this->keys->needs_rekey(); } - auto keys_needs_dump() { return this->keys->needs_dump(); } - auto keys_pending_config() { return this->keys->pending_config(); } - auto keys_encrypt_message(ustring_view plaintext, bool compress = true) const { - return this->keys->encrypt_message(plaintext, compress); - } - auto keys_decrypt_message(ustring_view ciphertext) const { - return this->keys->decrypt_message(ciphertext); - } + MetaGroup( + shared_ptr info, + shared_ptr members, + shared_ptr keys) : + MetaBase(), info{info}, members{members}, keys{keys} {} - private: - std::shared_ptr info; - std::shared_ptr members; - std::shared_ptr keys; + explicit MetaGroup(const Napi::CallbackInfo& info) {} }; } // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index a491041..2ae3244 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -11,60 +11,60 @@ MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap{info}, meta_group{constructGroupWrapper(info, "MetaGroupWrapper")} {} -// Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { -// return wrapResult(info, [&] { -// auto env = info.Env(); -// auto obj = Napi::Object::New(env); - -// obj["name"] = toJs(env, config.get_name()); -// obj["createdAtSeconds"] = toJs(env, config.get_created()); -// obj["deleteAttachBeforeSeconds"] = toJs(env, config.get_delete_attach_before()); -// obj["deleteBeforeSeconds"] = toJs(env, config.get_delete_before()); - -// if (auto expiry = config.get_expiry_timer(); expiry) -// obj["expirySeconds"] = toJs(env, expiry->count()); -// obj["isDestroyed"] = toJs(env, config.is_destroyed()); -// obj["profilePicture"] = toJs(env, config.get_profile_pic()); - -// return obj; -// }); -// } - -// Napi::Value MetaGroupWrapper::infoSet(const Napi::CallbackInfo& info) { -// return wrapResult(info, [&] { -// assertInfoLength(info, 1); -// auto arg = info[0]; -// assertIsObject(arg); -// auto obj = arg.As(); - -// if (auto name = maybeNonemptyString(obj.Get("name"), "MetaGroupWrapper::setInfo name")) -// config.set_name(*name); - -// if (auto created = maybeNonemptyInt( -// obj.Get("createdAtSeconds"), "MetaGroupWrapper::setInfo set_created")) -// config.set_created(std::move(*created)); - -// if (auto expiry = maybeNonemptyInt( -// obj.Get("expirySeconds"), "MetaGroupWrapper::setInfo set_expiry_timer")) -// config.set_expiry_timer(std::chrono::seconds{*expiry}); - -// if (auto deleteBefore = maybeNonemptyInt( -// obj.Get("deleteBeforeSeconds"), "MetaGroupWrapper::setInfo -// set_delete_before")) -// config.set_delete_before(std::move(*deleteBefore)); - -// if (auto deleteAttachBefore = maybeNonemptyInt( -// obj.Get("deleteAttachBeforeSeconds"), -// "MetaGroupWrapper::setInfo set_delete_attach_before")) -// config.set_delete_attach_before(std::move(*deleteAttachBefore)); - -// if (auto profilePicture = obj.Get("profilePicture")) { -// auto profilePic = profile_pic_from_object(profilePicture); -// config.set_profile_pic(profilePic); -// } - -// return this->getInfo(info); -// }); -// } +Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + auto obj = Napi::Object::New(env); + + obj["name"] = toJs(env, this->meta_group->info->get_name()); + obj["createdAtSeconds"] = toJs(env, this->meta_group->info->get_created()); + obj["deleteAttachBeforeSeconds"] = + toJs(env, this->meta_group->info->get_delete_attach_before()); + obj["deleteBeforeSeconds"] = toJs(env, this->meta_group->info->get_delete_before()); + + if (auto expiry = this->meta_group->info->get_expiry_timer(); expiry) + obj["expirySeconds"] = toJs(env, expiry->count()); + obj["isDestroyed"] = toJs(env, this->meta_group->info->is_destroyed()); + obj["profilePicture"] = toJs(env, this->meta_group->info->get_profile_pic()); + + return obj; + }); +} + +Napi::Value MetaGroupWrapper::infoSet(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + auto arg = info[0]; + assertIsObject(arg); + auto obj = arg.As(); + + if (auto name = maybeNonemptyString(obj.Get("name"), "MetaGroupWrapper::setInfo name")) + this->meta_group->info->set_name(*name); + + if (auto created = maybeNonemptyInt( + obj.Get("createdAtSeconds"), "MetaGroupWrapper::setInfo set_created")) + this->meta_group->info->set_created(std::move(*created)); + + if (auto expiry = maybeNonemptyInt( + obj.Get("expirySeconds"), "MetaGroupWrapper::setInfo set_expiry_timer")) + this->meta_group->info->set_expiry_timer(std::chrono::seconds{*expiry}); + + if (auto deleteBefore = maybeNonemptyInt( + obj.Get("deleteBeforeSeconds"), "MetaGroupWrapper::setInfo set_delete_before")) + this->meta_group->info->set_delete_before(std::move(*deleteBefore)); + + if (auto deleteAttachBefore = maybeNonemptyInt( + obj.Get("deleteAttachBeforeSeconds"), + "MetaGroupWrapper::setInfo set_delete_attach_before")) + this->meta_group->info->set_delete_attach_before(std::move(*deleteAttachBefore)); + + if (auto profilePicture = obj.Get("profilePicture")) { + auto profilePic = profile_pic_from_object(profilePicture); + this->meta_group->info->set_profile_pic(profilePic); + } + + return this->infoGet(info); + }); +} } // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 0fee26c..cd43f49 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -30,6 +30,35 @@ struct toJs_impl { } }; +using push_entry_t = std::pair< + std::string, + std::tuple< + session::config::seqno_t, + session::ustring, + std::vector>>>; + +using dump_entry_t = std::pair; + +Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry) { + auto obj = Napi::Object::New(env); + + obj["type"] = toJs(env, push_entry.first); + obj["seqno"] = toJs(env, std::get<0>(push_entry.second)); + obj["data"] = toJs(env, std::get<1>(push_entry.second)); + obj["seqno"] = toJs(env, std::get<2>(push_entry.second)); + + return obj; +}; + +Napi::Object dump_entry_to_JS(const Napi::Env& env, const dump_entry_t& dump_entry) { + auto obj = Napi::Object::New(env); + + obj["type"] = toJs(env, dump_entry.first); + obj["data"] = toJs(env, dump_entry.second); + + return obj; +}; + class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap { public: static void Init(Napi::Env env, Napi::Object exports) { @@ -42,9 +71,9 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapneeds_push(); }); + return wrapResult(info, [&] { + return this->meta_group->members->needs_push() || + this->meta_group->info + ->needs_push(); // || this->meta_group->keys->needs_rekey() // TODO see + // what to do with this and needs_rekey below + }); + } + + Napi::Value push(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + + vector to_push; + if (this->meta_group->members->needs_push()) { + auto memberPush = push_entry_to_JS( + env, std::make_pair("GroupMember"s, this->meta_group->members->push())); + to_push.push_back(memberPush); + } + + if (this->meta_group->info->needs_push()) { + auto infosPush = push_entry_to_JS( + env, std::make_pair("GroupInfo"s, this->meta_group->info->push())); + to_push.push_back(infosPush); + } + // TODO see what to do with this and needs_rekey below + // if (this->meta_group->keys->needs_rekey()) { + // to_push.push_back(std::make_pair("GroupKeys"s, this->meta_group->keys_rekey())); + // } + return to_push; + }); + } + + Napi::Value needsDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + return this->meta_group->members->needs_dump() || + this->meta_group->info->needs_dump() || this->meta_group->keys->needs_dump(); + }); + } + + Napi::Value dump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + + vector to_dump; + if (this->meta_group->members->needs_dump()) { + auto memberDump = dump_entry_to_JS( + env, std::make_pair("GroupMember"s, this->meta_group->members->dump())); + to_dump.push_back(memberDump); + } + + if (this->meta_group->info->needs_dump()) { + auto infoDump = dump_entry_to_JS( + env, std::make_pair("GroupInfo"s, this->meta_group->members->dump())); + to_dump.push_back(infoDump); + } + + if (this->meta_group->keys->needs_dump()) { + auto keysDump = dump_entry_to_JS( + env, std::make_pair("GroupKeys"s, this->meta_group->members->dump())); + to_dump.push_back(keysDump); + } + + return to_dump; + }); } /** Info Actions */ - // Napi::Value infoGet(const Napi::CallbackInfo& info); + Napi::Value infoGet(const Napi::CallbackInfo& info); - // Napi::Value infoSet(const Napi::CallbackInfo& info); + Napi::Value infoSet(const Napi::CallbackInfo& info); - // Napi::Value infoDestroy(const Napi::CallbackInfo& info) { - // return wrapResult(info, [&] { - // meta_group->destroy_group(); - // return meta_group->info_get(info); - // }); - // } + Napi::Value infoDestroy(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + meta_group->info->destroy_group(); + return this->infoGet(info); + }); + } /** Members Actions */ Napi::Value memberGetAll(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->member_get_all(); }); + return wrapResult(info, [&] { + std::vector allMembers; + for (auto& member : *this->meta_group->members) { + allMembers.push_back(member); + } + return allMembers; + }); } Napi::Value memberGet(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { auto env = info.Env(); assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - return meta_group->member_get(pubkeyHex); + return meta_group->members->get(pubkeyHex); }); } @@ -114,7 +220,7 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmember_get_or_construct(pubkeyHex); + return meta_group->members->get_or_construct(pubkeyHex); }); } @@ -125,9 +231,10 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->member_get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.set_name(newName); - return this->meta_group->member_set(m); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); }); } @@ -137,23 +244,24 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->member_get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.set_invited(failed); - return this->meta_group->member_set(m); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); }); } Napi::Value memberSetAccepted(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto m = this->meta_group->member_get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.set_accepted(); - return this->meta_group->member_set(m); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); }); } @@ -164,10 +272,11 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->member_get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.set_promoted(failed); - return this->meta_group->member_set(m); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); }); } @@ -181,9 +290,10 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->member_get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.profile_picture = profilePicture; - return this->meta_group->member_set(m); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); }); } @@ -194,9 +304,9 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap result; auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto erased = this->meta_group->member_erase(pubkeyHex); + auto erased = this->meta_group->members->erase(pubkeyHex); if (erased) { - meta_group->keys_rekey(); + meta_group->keys->rekey(*(this->meta_group->info), *(this->meta_group->members)); } return erased; @@ -206,11 +316,60 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapkeys_needs_rekey(); }); + return wrapResult(info, [&] { return meta_group->keys->needs_rekey(); }); } Napi::Value keyRekey(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->keys_rekey(); }); + return wrapResult(info, [&] { + return meta_group->keys->rekey(*(meta_group->info), *(meta_group->members)); + }); + } + + // TODO key_supplement, swarm_make_subaccount, ... + + Napi::Value loadKeyMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 3); + assertIsString(info[0]); + assertIsUInt8Array(info[1]); + assertIsNumber(info[2]); + + auto hash = toCppString(info[0], __PRETTY_FUNCTION__); + auto data = toCppBuffer(info[1], __PRETTY_FUNCTION__); + auto timestamp_ms = toCppInteger(info[2], __PRETTY_FUNCTION__); + + return meta_group->keys->load_key_message( + hash, + data, + timestamp_ms, + *(this->meta_group->info), + *(this->meta_group->members)); + }); + } + + Napi::Value currentHashes(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); + } + + Napi::Value encryptMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsUInt8Array(info[0]); + assertIsBoolean(info[1]); + + auto plaintext = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto compress = toCppBoolean(info[1], __PRETTY_FUNCTION__); + return this->meta_group->keys->encrypt_message(plaintext, compress); + }); + } + Napi::Value decryptMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsUInt8Array(info[0]); + + auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); + return this->meta_group->keys->decrypt_message(ciphertext); + }); } }; diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 5cb6a66..6901108 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -64,7 +64,6 @@ struct toJs_impl { obj["pubkeyHex"] = toJs(env, info.id); obj["secretKey"] = toJs(env, info.secretkey); - obj["authSig"] = toJs(env, info.auth_sig); obj["priority"] = toJs(env, info.priority); obj["joinedAtSeconds"] = toJs(env, info.joined_at); diff --git a/src/utilities.hpp b/src/utilities.hpp index bc0833b..feddb23 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "session/types.hpp" @@ -125,6 +126,17 @@ struct toJs_impl> { } }; template +struct toJs_impl> { + auto operator()(const Napi::Env& env, const std::unordered_set& set) { + std::vector as_array(set.begin(), set.end()); + + auto arr = Napi::Array::New(env, as_array.size()); + for (size_t i = 0; i < as_array.size(); i++) + arr[i] = toJs(env, as_array[i]); + return arr; + } +}; +template struct toJs_impl> { Napi::Value operator()(const Napi::Env& env, const std::optional& val) { if (val) diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts new file mode 100644 index 0000000..868bbcd --- /dev/null +++ b/types/groups/groupkeys.d.ts @@ -0,0 +1,17 @@ +/// + +declare module 'libsession_util_nodejs' { + type SubWrapperType = 'GroupInfo' | 'GroupMember' | 'GroupKeys'; + + export type GroupKeysWrapper = { + keysNeedsRekey: () => boolean; + keyRekey: () => Uint8Array; + groupKeys: () => Array; + + loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; + currentHashes: () => Array; + + encryptMessage: (plaintext: Uint8Array, compress: boolean) => Uint8Array; + decryptMessage: (ciphertext: Uint8Array) => Uint8Array | null; + }; +} diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 32adff0..213bd3d 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -1,9 +1,10 @@ /// /// /// +/// declare module 'libsession_util_nodejs' { - type ConstructorOptions = { + export type GroupWrapperConstructor = { userEd25519Secretkey: Uint8Array; groupEd25519Pubkey: Uint8Array; groupEd25519Secretkey: Uint8Array | null; @@ -13,27 +14,33 @@ declare module 'libsession_util_nodejs' { }; type MetaGroupWrapper = GroupInfoWrapper & - GroupMemberWrapper & { - init: (options: ConstructorOptions) => void; - + GroupMemberWrapper & + GroupKeysWrapper & { // shared actions + init: (options: GroupWrapperConstructor) => void; needsPush: () => boolean; - - // info - - // members - - // keys - keysNeedsRekey: () => boolean; + push: () => Array<{ type: SubWrapperType; data: Uint8Array; seqno: number }>; + needsDump: () => boolean; + dump: () => Array<{ type: SubWrapperType; data: Uint8Array }>; }; - export type MetaGroupWrapperActionsCalls = MakeWrapperActionCalls; + // this just adds an argument of type GroupPubkeyType in front of the parameters of that function + type AddGroupPkToFunction any> = ( + ...args: [GroupPubkeyType, ...Parameters] + ) => ReturnType; + + export type MetaGroupWrapperActionsCalls = MakeWrapperActionCalls<{ + [key in keyof MetaGroupWrapper]: AddGroupPkToFunction; + }>; export class MetaGroupWrapperNode { - constructor(ConstructorOptions); + constructor(GroupWrapperConstructor); // shared actions public needsPush: MetaGroupWrapper['needsPush']; + public push: MetaGroupWrapper['push']; + public needsDump: MetaGroupWrapper['needsDump']; + public dump: MetaGroupWrapper['dump']; // info public infoGet: MetaGroupWrapper['infoGet']; @@ -49,16 +56,26 @@ declare module 'libsession_util_nodejs' { public memberSetPromoted: MetaGroupWrapper['memberSetPromoted']; public memberSetInvited: MetaGroupWrapper['memberSetInvited']; public memberErase: MetaGroupWrapper['memberErase']; + public memberSetProfilePicture: MetaGroupWrapper['memberSetProfilePicture']; // keys public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; + public keyRekey: MetaGroupWrapper['keyRekey']; + public groupKeys: MetaGroupWrapper['groupKeys']; + public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; + public currentHashes: MetaGroupWrapper['currentHashes']; + public encryptMessage: MetaGroupWrapper['encryptMessage']; + public decryptMessage: MetaGroupWrapper['decryptMessage']; } export type MetaGroupActionsType = - | ['init', ConstructorOptions] + | ['init', GroupWrapperConstructor] // shared actions | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall // info actions | MakeActionCall @@ -74,7 +91,14 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall // keys actions - | MakeActionCall; + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall; } diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index c41ff86..b4760d4 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -41,7 +41,6 @@ declare module 'libsession_util_nodejs' { export type CreateGroupResult = BaseGroupInfo & { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. secretKey: Uint8Array; - authSig: string; }; type UserGroupsWrapper = BaseConfigWrapper & { From 088fa82500224f8d938a6115dfe304a59fe4972e Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 6 Sep 2023 18:25:21 +1000 Subject: [PATCH 08/64] broken state after metagroup dump and load --- libsession-util | 2 +- src/groups/meta_group_wrapper.hpp | 138 ++++++++++++------------------ src/meta/meta_base_wrapper.cpp | 3 - src/meta/meta_base_wrapper.hpp | 33 +++++-- types/groups/groupkeys.d.ts | 2 - types/groups/metagroup.d.ts | 18 ++-- types/shared.d.ts | 2 + 7 files changed, 93 insertions(+), 105 deletions(-) delete mode 100644 src/meta/meta_base_wrapper.cpp diff --git a/libsession-util b/libsession-util index 517a61a..c272e06 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 517a61a455d31cd9363198d1b3d02f20093a5811 +Subproject commit c272e06f53b08d7b6eb92d39a7ac83c44c62eb41 diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index cd43f49..ccf8274 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -6,6 +6,7 @@ #include "../profile_pic.hpp" #include "../utilities.hpp" #include "./meta_group.hpp" +#include "oxenc/bt_producer.h" namespace session::nodeapi { using config::groups::Members; @@ -30,31 +31,17 @@ struct toJs_impl { } }; -using push_entry_t = std::pair< - std::string, - std::tuple< - session::config::seqno_t, - session::ustring, - std::vector>>>; - -using dump_entry_t = std::pair; +using push_entry_t = std::tuple< + session::config::seqno_t, + session::ustring, + std::vector>>; Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry) { auto obj = Napi::Object::New(env); - obj["type"] = toJs(env, push_entry.first); - obj["seqno"] = toJs(env, std::get<0>(push_entry.second)); - obj["data"] = toJs(env, std::get<1>(push_entry.second)); - obj["seqno"] = toJs(env, std::get<2>(push_entry.second)); - - return obj; -}; - -Napi::Object dump_entry_to_JS(const Napi::Env& env, const dump_entry_t& dump_entry) { - auto obj = Napi::Object::New(env); - - obj["type"] = toJs(env, dump_entry.first); - obj["data"] = toJs(env, dump_entry.second); + obj["seqno"] = toJs(env, std::get<0>(push_entry)); + obj["data"] = toJs(env, std::get<1>(push_entry)); + obj["hashes"] = toJs(env, std::get<2>(push_entry)); return obj; }; @@ -68,37 +55,42 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap to_push; - if (this->meta_group->members->needs_push()) { - auto memberPush = push_entry_to_JS( - env, std::make_pair("GroupMember"s, this->meta_group->members->push())); - to_push.push_back(memberPush); - } + to_push["GroupMember"s] = push_entry_to_JS(env, this->meta_group->members->push()); + to_push["GroupInfo"s] = push_entry_to_JS(env, this->meta_group->info->push()); - if (this->meta_group->info->needs_push()) { - auto infosPush = push_entry_to_JS( - env, std::make_pair("GroupInfo"s, this->meta_group->info->push())); - to_push.push_back(infosPush); - } - // TODO see what to do with this and needs_rekey below - // if (this->meta_group->keys->needs_rekey()) { - // to_push.push_back(std::make_pair("GroupKeys"s, this->meta_group->keys_rekey())); + // TODO see what to do with this and needs_rekey below? + // to_push.push_back(std::make_pair("GroupKeys"s, + // this->meta_group->keys_rekey())); // } return to_push; }); @@ -150,30 +134,20 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap to_dump; - if (this->meta_group->members->needs_dump()) { - auto memberDump = dump_entry_to_JS( - env, std::make_pair("GroupMember"s, this->meta_group->members->dump())); - to_dump.push_back(memberDump); - } + oxenc::bt_dict_producer combined; - if (this->meta_group->info->needs_dump()) { - auto infoDump = dump_entry_to_JS( - env, std::make_pair("GroupInfo"s, this->meta_group->members->dump())); - to_dump.push_back(infoDump); - } - - if (this->meta_group->keys->needs_dump()) { - auto keysDump = dump_entry_to_JS( - env, std::make_pair("GroupKeys"s, this->meta_group->members->dump())); - to_dump.push_back(keysDump); - } + // NB: the keys have to be in ascii-sorted order: + combined.append("info", session::from_unsigned_sv(this->meta_group->info->dump())); + combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->dump())); + combined.append( + "members", session::from_unsigned_sv(this->meta_group->members->dump())); + auto to_dump = std::move(combined).str(); // Will be a std::string, but contains binary - return to_dump; + return to_unsigned_sv(to_dump); }); } diff --git a/src/meta/meta_base_wrapper.cpp b/src/meta/meta_base_wrapper.cpp deleted file mode 100644 index 97f9f02..0000000 --- a/src/meta/meta_base_wrapper.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -#include "base_config.hpp" diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 9749b45..7645329 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -10,7 +10,7 @@ namespace session::nodeapi { class MetaBaseWrapper { public: - explicit MetaBaseWrapper(); + explicit MetaBaseWrapper(){}; virtual ~MetaBaseWrapper() = default; @@ -37,6 +37,7 @@ class MetaBaseWrapper { if (!info.IsConstructCall()) throw std::invalid_argument{ "You need to call the constructor with the `new` syntax"}; + throw std::invalid_argument{"PLOP"}; assertInfoLength(info, 1); auto arg = info[0]; @@ -60,12 +61,30 @@ class MetaBaseWrapper { obj.Get("groupEd25519Secretkey"), class_name + ":constructGroupWrapper.groupEd25519Secretkey"); - std::optional dumped_info = maybeNonemptyBuffer( - obj.Get("dumpedInfo"), class_name + ":constructGroupWrapper.dumpedInfo"); - std::optional dumped_members = maybeNonemptyBuffer( - obj.Get("dumpedMembers"), class_name + ":constructGroupWrapper.dumpedMembers"); - std::optional dumped_keys = maybeNonemptyBuffer( - obj.Get("dumpedKeys"), class_name + ":constructGroupWrapper.dumpedKeys"); + std::optional dumped_meta = maybeNonemptyBuffer( + obj.Get("metaDumped"), class_name + ":constructGroupWrapper.metaDumped"); + + std::optional dumped_info; + std::optional dumped_members; + std::optional dumped_keys; + + if (dumped_meta) { + auto dumped_meta_str = from_unsigned_sv(*dumped_meta); + + oxenc::bt_dict_consumer combined{dumped_meta_str}; + // NB: must read in ascii-sorted order: + if (!combined.skip_until("info")) + throw std::runtime_error{"info dump not found in combined dump!"}; + dumped_info = session::to_unsigned_sv(combined.consume_string_view()); + + if (!combined.skip_until("keys")) + throw std::runtime_error{"keys dump not found in combined dump!"}; + dumped_keys = session::to_unsigned_sv(combined.consume_string_view()); + + if (!combined.skip_until("members")) + throw std::runtime_error{"members dump not found in combined dump!"}; + dumped_members = session::to_unsigned_sv(combined.consume_string_view()); + } auto info = std::make_shared( group_ed25519_pubkey, group_ed25519_secretkey, dumped_info); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 868bbcd..2825b00 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -1,8 +1,6 @@ /// declare module 'libsession_util_nodejs' { - type SubWrapperType = 'GroupInfo' | 'GroupMember' | 'GroupKeys'; - export type GroupKeysWrapper = { keysNeedsRekey: () => boolean; keyRekey: () => Uint8Array; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 213bd3d..88fcfa5 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -6,11 +6,9 @@ declare module 'libsession_util_nodejs' { export type GroupWrapperConstructor = { userEd25519Secretkey: Uint8Array; - groupEd25519Pubkey: Uint8Array; - groupEd25519Secretkey: Uint8Array | null; - dumpedInfo: Uint8Array | null; - dumpedMembers: Uint8Array | null; - dumpedKeys: Uint8Array | null; + groupEd25519Pubkey: Uint8Array; // the ed25519 pubkey without the 03 prefix + groupEd25519Secretkey: Uint8Array | null; // the ed25519 privkey if we have it (comes from usergroup wrapper if we have it) + metaDumped: Uint8Array | null; }; type MetaGroupWrapper = GroupInfoWrapper & @@ -19,9 +17,9 @@ declare module 'libsession_util_nodejs' { // shared actions init: (options: GroupWrapperConstructor) => void; needsPush: () => boolean; - push: () => Array<{ type: SubWrapperType; data: Uint8Array; seqno: number }>; + push: () => { [T in Exclude]: PushConfigResult }; // GroupKeys push comes from rekey() and has no hashes etc associated. needsDump: () => boolean; - dump: () => Array<{ type: SubWrapperType; data: Uint8Array }>; + metaDump: () => Uint8Array; }; // this just adds an argument of type GroupPubkeyType in front of the parameters of that function @@ -34,13 +32,13 @@ declare module 'libsession_util_nodejs' { }>; export class MetaGroupWrapperNode { - constructor(GroupWrapperConstructor); + constructor(options: GroupWrapperConstructor); // shared actions public needsPush: MetaGroupWrapper['needsPush']; public push: MetaGroupWrapper['push']; public needsDump: MetaGroupWrapper['needsDump']; - public dump: MetaGroupWrapper['dump']; + public metaDump: MetaGroupWrapper['metaDump']; // info public infoGet: MetaGroupWrapper['infoGet']; @@ -75,7 +73,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall // info actions | MakeActionCall diff --git a/types/shared.d.ts b/types/shared.d.ts index b898329..75046a6 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -91,6 +91,7 @@ declare module 'libsession_util_nodejs' { }; export type PriorityType = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned + type GroupSubWrapperType = 'GroupInfo' | 'GroupMember' | 'GroupKeys'; type GroupInfoShared = { name: string | null; @@ -103,5 +104,6 @@ declare module 'libsession_util_nodejs' { export type GroupInfoGet = GroupInfoShared & { isDestroyed: boolean; + secretKey?: Uint8Array; }; } From 6fb94466088c330e1f20f8f77b38dacd061694dd Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 6 Sep 2023 18:30:50 +1000 Subject: [PATCH 09/64] chore: removed useless metabase --- src/groups/meta_group.hpp | 5 ++--- src/meta/meta_base.cpp | 11 ----------- src/meta/meta_base.hpp | 15 --------------- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 src/meta/meta_base.cpp delete mode 100644 src/meta/meta_base.hpp diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index 32b127a..dfc8db5 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -2,7 +2,6 @@ #include -#include "../meta/meta_base.hpp" #include "session/config/groups/info.hpp" #include "session/config/groups/keys.hpp" #include "session/config/groups/members.hpp" @@ -21,7 +20,7 @@ using std::vector; using std::make_shared; using std::shared_ptr; -class MetaGroup : public MetaBase { +class MetaGroup { public: shared_ptr info; shared_ptr members; @@ -31,7 +30,7 @@ class MetaGroup : public MetaBase { shared_ptr info, shared_ptr members, shared_ptr keys) : - MetaBase(), info{info}, members{members}, keys{keys} {} + info{info}, members{members}, keys{keys} {} explicit MetaGroup(const Napi::CallbackInfo& info) {} }; diff --git a/src/meta/meta_base.cpp b/src/meta/meta_base.cpp deleted file mode 100644 index 3296e16..0000000 --- a/src/meta/meta_base.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "meta_base.hpp" - -#include - -#include "session/types.hpp" - -namespace session::nodeapi { - -MetaBase::MetaBase() {} - -} // namespace session::nodeapi diff --git a/src/meta/meta_base.hpp b/src/meta/meta_base.hpp deleted file mode 100644 index 4ae1d33..0000000 --- a/src/meta/meta_base.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -#include "../base_config.hpp" - -namespace session::nodeapi { - -class MetaBase { - - public: - explicit MetaBase(); -}; - -} // namespace session::nodeapi From fbe6c5d2539872b4902932550ac5a49211d519e6 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 7 Sep 2023 13:30:50 +1000 Subject: [PATCH 10/64] feat: first working version with metagroup wrapper --- CMakeLists.txt | 2 +- src/addon.cpp | 5 +-- src/base_config.hpp | 37 ---------------- src/groups/meta_group.hpp | 2 +- src/groups/meta_group_wrapper.cpp | 69 ++++++++++++++++++++++++++++-- src/groups/meta_group_wrapper.hpp | 70 +++---------------------------- src/meta/meta_base_wrapper.hpp | 1 - types/groups/metagroup.d.ts | 6 +-- types/shared.d.ts | 20 ++++++++- types/user/userconfig.d.ts | 4 +- types/user/usergroups.d.ts | 2 +- 11 files changed, 100 insertions(+), 118 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 731e5a0..da0c432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -file(GLOB SOURCE_FILES src/*.cpp) +file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp) add_subdirectory(libsession-util) diff --git a/src/addon.cpp b/src/addon.cpp index 75b8ff6..fce67d9 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -8,6 +8,8 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { using namespace session::nodeapi; + // Group wrappers init + MetaGroupWrapper::Init(env, exports); // User wrappers init UserConfigWrapper::Init(env, exports); @@ -15,9 +17,6 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { UserGroupsWrapper::Init(env, exports); ConvoInfoVolatileWrapper::Init(env, exports); - // Group wrappers init - MetaGroupWrapper::Init(env, exports); - return exports; } diff --git a/src/base_config.hpp b/src/base_config.hpp index 27a233c..febda54 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -106,43 +106,6 @@ class ConfigBaseImpl { }); } - // Constructs a shared_ptr of some config::ConfigBase-derived type, taking a secret key and - // optional dump. This is what most Config types require, but a subclass could replace this if - // it needs to do something else. - template < - typename Config, - std::enable_if_t, int> = 0> - static std::shared_ptr construct3Args( - const Napi::CallbackInfo& info, const std::string& class_name) { - return wrapExceptions(info, [&] { - if (!info.IsConstructCall()) - throw std::invalid_argument{ - "You need to call the constructor with the `new` syntax"}; - - assertInfoLength(info, 3); - - // we should get ed25519_pubkey as string (with 03 prefix), as first arg, secret key as - // second opt arg and optional dumped as third arg - assertIsString(info[0]); - assertIsUInt8ArrayOrNull(info[1]); - assertIsUInt8ArrayOrNull(info[2]); - std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); - std::optional secret_key; - auto second = info[1]; - if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) - secret_key = toCppBufferView(second, class_name + ".new.secret"); - - std::optional dump; - auto third = info[2]; - if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) - dump = toCppBufferView(third, class_name + ".new.dump"); - - auto withoutPrefix = ed25519_pubkey_str.substr(2); - ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); - return std::make_shared(ed25519_pubkey, secret_key, dump); - }); - } - virtual ~ConfigBaseImpl() = default; // Accesses a reference the stored config instance as `std::shared_ptr` (if no template is diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index dfc8db5..b557988 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -30,7 +30,7 @@ class MetaGroup { shared_ptr info, shared_ptr members, shared_ptr keys) : - info{info}, members{members}, keys{keys} {} + info{info}, members{members}, keys{keys} {}; explicit MetaGroup(const Napi::CallbackInfo& info) {} }; diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 2ae3244..4242d19 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -6,10 +6,73 @@ namespace session::nodeapi { +Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry) { + auto obj = Napi::Object::New(env); + + obj["seqno"] = toJs(env, std::get<0>(push_entry)); + obj["data"] = toJs(env, std::get<1>(push_entry)); + obj["hashes"] = toJs(env, std::get<2>(push_entry)); + + return obj; +}; + MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : - MetaBaseWrapper{}, - Napi::ObjectWrap{info}, - meta_group{constructGroupWrapper(info, "MetaGroupWrapper")} {} + meta_group{MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper")}, + Napi::ObjectWrap{info} {} + +void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { + MetaBaseWrapper::NoBaseClassInitHelper( + env, + exports, + "MetaGroupWrapperNode", + { + // shared exposed functions + + InstanceMethod("needsPush", &MetaGroupWrapper::needsPush), + InstanceMethod("push", &MetaGroupWrapper::push), + InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), + InstanceMethod("metaDump", &MetaGroupWrapper::metaDump), + + // infos exposed functions + InstanceMethod("infoGet", &MetaGroupWrapper::infoGet), + InstanceMethod("infoSet", &MetaGroupWrapper::infoSet), + InstanceMethod("infoDestroy", &MetaGroupWrapper::infoDestroy), + + // members exposed functions + InstanceMethod("memberGet", &MetaGroupWrapper::memberGet), + InstanceMethod("memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), + InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), + InstanceMethod("memberSetName", &MetaGroupWrapper::memberSetName), + InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), + InstanceMethod("memberSetAccepted", &MetaGroupWrapper::memberSetAccepted), + InstanceMethod("memberSetPromoted", &MetaGroupWrapper::memberSetPromoted), + InstanceMethod( + "memberSetProfilePicture", &MetaGroupWrapper::memberSetProfilePicture), + InstanceMethod("memberErase", &MetaGroupWrapper::memberErase), + + // keys exposed functions + + InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), + InstanceMethod("keyRekey", &MetaGroupWrapper::keyRekey), + + InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), + InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), + + InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), + InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), + + }); +} + +Napi::Value MetaGroupWrapper::needsPush(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + return this->meta_group->members->needs_push() || + this->meta_group->info + ->needs_push(); // || this->meta_group->keys->needs_rekey() // TODO + // see what to do with this and needs_rekey below + }); +} Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index ccf8274..cabac03 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -36,64 +36,11 @@ using push_entry_t = std::tuple< session::ustring, std::vector>>; -Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry) { - auto obj = Napi::Object::New(env); +Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry); - obj["seqno"] = toJs(env, std::get<0>(push_entry)); - obj["data"] = toJs(env, std::get<1>(push_entry)); - obj["hashes"] = toJs(env, std::get<2>(push_entry)); - - return obj; -}; - -class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrap { +class MetaGroupWrapper : public Napi::ObjectWrap { public: - static void Init(Napi::Env env, Napi::Object exports) { - NoBaseClassInitHelper( - env, - exports, - "MetaGroupWrapperNode", - { - // shared exposed functions - - InstanceMethod("needsPush", &MetaGroupWrapper::needsPush), - InstanceMethod("push", &MetaGroupWrapper::push), - InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), - InstanceMethod("metaDump", &MetaGroupWrapper::metaDump), - - // infos exposed functions - // InstanceMethod("infoGet", &MetaGroupWrapper::infoGet), - // InstanceMethod("infoSet", &MetaGroupWrapper::infoSet), - // InstanceMethod("infoDestroy", &MetaGroupWrapper::infoDestroy), - - // // members exposed functions - // InstanceMethod("memberGet", &MetaGroupWrapper::memberGet), - // InstanceMethod( - // "memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), - // InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), - // InstanceMethod("memberSetName", &MetaGroupWrapper::memberSetName), - // InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), - // InstanceMethod("memberSetAccepted", - // &MetaGroupWrapper::memberSetAccepted), - // InstanceMethod("memberSetPromoted", - // &MetaGroupWrapper::memberSetPromoted), InstanceMethod( - // "memberSetProfilePicture", - // &MetaGroupWrapper::memberSetProfilePicture), - // InstanceMethod("memberErase", &MetaGroupWrapper::memberErase), - - // // keys exposed functions - - // InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), - // InstanceMethod("keyRekey", &MetaGroupWrapper::keyRekey), - - // InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), - // InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), - - // InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), - // InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), - - }); - } + static void Init(Napi::Env env, Napi::Object exports); explicit MetaGroupWrapper(const Napi::CallbackInfo& info); @@ -102,14 +49,7 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->members->needs_push() || - this->meta_group->info - ->needs_push(); // || this->meta_group->keys->needs_rekey() // TODO see - // what to do with this and needs_rekey below - }); - } + Napi::Value needsPush(const Napi::CallbackInfo& info); Napi::Value push(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { @@ -145,7 +85,7 @@ class MetaGroupWrapper : public MetaBaseWrapper, public Napi::ObjectWrapmeta_group->keys->dump())); combined.append( "members", session::from_unsigned_sv(this->meta_group->members->dump())); - auto to_dump = std::move(combined).str(); // Will be a std::string, but contains binary + auto to_dump = std::move(combined).str(); return to_unsigned_sv(to_dump); }); diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 7645329..26a4859 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -37,7 +37,6 @@ class MetaBaseWrapper { if (!info.IsConstructCall()) throw std::invalid_argument{ "You need to call the constructor with the `new` syntax"}; - throw std::invalid_argument{"PLOP"}; assertInfoLength(info, 1); auto arg = info[0]; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 88fcfa5..d860967 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -5,9 +5,9 @@ declare module 'libsession_util_nodejs' { export type GroupWrapperConstructor = { - userEd25519Secretkey: Uint8Array; - groupEd25519Pubkey: Uint8Array; // the ed25519 pubkey without the 03 prefix - groupEd25519Secretkey: Uint8Array | null; // the ed25519 privkey if we have it (comes from usergroup wrapper if we have it) + userEd25519Secretkey: FixedSizeUint8Array<64>; + groupEd25519Pubkey: FixedSizeUint8Array<32>; // the ed25519 pubkey without the 03 prefix + groupEd25519Secretkey: FixedSizeUint8Array<64> | null; // the ed25519 privkey if we have it (comes from usergroup wrapper if we have it) metaDumped: Uint8Array | null; }; diff --git a/types/shared.d.ts b/types/shared.d.ts index 75046a6..b2bc25c 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -1,4 +1,22 @@ declare module 'libsession_util_nodejs' { + type FixedSizeArray = N extends N + ? number extends N + ? T[] + : _FixedSizeArray + : never; + type _FixedSizeArray = R['length'] extends N + ? R + : _FixedSizeArray; + + type KnownKeys = { + [K in keyof T]: string extends K ? never : number extends K ? never : K; + } extends { [_ in keyof T]: infer U } + ? U + : never; + type Uint8ArrayWithoutIndex = Pick>; + + type FixedSizeUint8Array = FixedSizeArray & Uint8ArrayWithoutIndex; + type AsyncWrapper any> = ( ...args: Parameters ) => Promise>; @@ -104,6 +122,6 @@ declare module 'libsession_util_nodejs' { export type GroupInfoGet = GroupInfoShared & { isDestroyed: boolean; - secretKey?: Uint8Array; + secretKey?: FixedSizeUint8Array<64>; }; } diff --git a/types/user/userconfig.d.ts b/types/user/userconfig.d.ts index 1ec35fa..54d65b1 100644 --- a/types/user/userconfig.d.ts +++ b/types/user/userconfig.d.ts @@ -13,13 +13,13 @@ declare module 'libsession_util_nodejs' { name: string; priority: number; url: string; - key: Uint8Array; + key: Uint8Array; // FixedSizeUint8Array<32> // expirySeconds: number | null; // <= 0 is returned as null }; setUserInfo: ( name: string, priority: number, - profilePic: { url: string; key: Uint8Array } | null + profilePic: { url: string; key: Uint8Array } | null // FixedSizeUint8Array<32> // expirySeconds: number, ) => void; setEnableBlindedMsgRequest: (msgRequest: boolean) => void; diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index b4760d4..cb50289 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -40,7 +40,7 @@ declare module 'libsession_util_nodejs' { export type CreateGroupResult = BaseGroupInfo & { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. - secretKey: Uint8Array; + secretKey: FixedSizeUint8Array<64>; }; type UserGroupsWrapper = BaseConfigWrapper & { From 4c83eaf2a2306a3bfa2b716df20d7cfbb91f2ab7 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 7 Sep 2023 15:38:38 +1000 Subject: [PATCH 11/64] feat: add groups set, erase and getAll from usergroups --- src/groups/meta_group_wrapper.cpp | 3 ++ src/user_groups_config.cpp | 58 +++++++++++++++++++++++++++++-- src/user_groups_config.hpp | 6 ++-- types/groups/groupinfo.d.ts | 1 - types/shared.d.ts | 16 ++++++++- types/user/usergroups.d.ts | 38 +++++++++++++------- 6 files changed, 101 insertions(+), 21 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 4242d19..ec4b7aa 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -87,6 +87,9 @@ Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { if (auto expiry = this->meta_group->info->get_expiry_timer(); expiry) obj["expirySeconds"] = toJs(env, expiry->count()); + else + obj["expirySeconds"] = env.Null(); + obj["isDestroyed"] = toJs(env, this->meta_group->info->is_destroyed()); obj["profilePicture"] = toJs(env, this->meta_group->info->get_profile_pic()); diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 6901108..a2df062 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -97,9 +97,9 @@ void UserGroupsWrapper::Init(Napi::Env env, Napi::Object exports) { // Groups related methods InstanceMethod("createGroup", &UserGroupsWrapper::createGroup), InstanceMethod("getGroup", &UserGroupsWrapper::getGroup), - // InstanceMethod("getAllGroups", &UserGroupsWrapper::getAllGroups), - // InstanceMethod("setGroup", &UserGroupsWrapper::setGroup), - // InstanceMethod("eraseGroup", &UserGroupsWrapper::eraseGroup), + InstanceMethod("getAllGroups", &UserGroupsWrapper::getAllGroups), + InstanceMethod("setGroup", &UserGroupsWrapper::setGroup), + InstanceMethod("eraseGroup", &UserGroupsWrapper::eraseGroup), }); } @@ -274,4 +274,56 @@ Napi::Value UserGroupsWrapper::getGroup(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return config.get_group(getStringArgs<1>(info)); }); } +Napi::Value UserGroupsWrapper::getAllGroups(const Napi::CallbackInfo& info) { + return get_all_impl(info, config.size_groups(), config.begin_groups(), config.end()); +} + +Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto obj = info[0].As(); + + if (obj.IsEmpty()) + throw std::invalid_argument("setGroup received empty"); + + assertIsString(obj.Get("pubkeyHex")); + auto groupPk = toCppString(obj.Get("pubkeyHex"), "legacyGroup.set"); + + // we should get a `UserGroupsSet` object. If any fields are null, skip updating them. + // Otherwise, use the corresponding value to update what we got from the + // `get_or_construct_group` below + + auto group_info = config.get_or_construct_group(groupPk); + + if (auto priority = + maybeNonemptyInt(obj.Get("priority"), "UserGroupsWrapper::setGroup priority")) { + group_info.priority = toPriority(obj.Get("priority"), group_info.priority); + } + + if (auto joinedAtSeconds = maybeNonemptyInt( + obj.Get("joinedAtSeconds"), "UserGroupsWrapper::setGroup joinedAtSeconds")) { + group_info.joined_at = *joinedAtSeconds; + } + + if (auto secretKey = maybeNonemptyBuffer( + obj.Get("secretKey"), "UserGroupsWrapper::setGroup secretKey")) { + group_info.secretkey = *secretKey; + } + + if (auto authData = maybeNonemptyBuffer( + obj.Get("authData"), "UserGroupsWrapper::setGroup authData")) { + group_info.auth_data = *authData; + } + + config.set(group_info); + + return config.get_or_construct_group(groupPk); + }); +} + +Napi::Value UserGroupsWrapper::eraseGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.erase_group(getStringArgs<1>(info)); }); +} + } // namespace session::nodeapi diff --git a/src/user_groups_config.hpp b/src/user_groups_config.hpp index bbe12c3..7134491 100644 --- a/src/user_groups_config.hpp +++ b/src/user_groups_config.hpp @@ -32,9 +32,9 @@ class UserGroupsWrapper : public ConfigBaseImpl, public Napi::ObjectWrap>; - type FixedSizeUint8Array = FixedSizeArray & Uint8ArrayWithoutIndex; + /** + * Allow a single type to be Nullable. i.e. string => string | null + */ + type Nullable = T | null; + + /** + * Allow all the fields of a type to be -themselves- nullable. + * i.e. {field1: string, field2: number} => {field1: string | null, field2: number | null} + */ + type AllFieldsNullable = { + [P in keyof T]: Nullable; + }; + type AsyncWrapper any> = ( ...args: Parameters ) => Promise>; @@ -124,4 +136,6 @@ declare module 'libsession_util_nodejs' { isDestroyed: boolean; secretKey?: FixedSizeUint8Array<64>; }; + + export type GroupInfoSet = GroupInfoShared & {}; } diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index cb50289..36656c8 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -25,11 +25,11 @@ declare module 'libsession_util_nodejs' { isAdmin: boolean; }; - type BaseGroupInfo = PriorityType & { + type BaseUserGroup = PriorityType & { joinedAtSeconds: number; // equivalent to the lastJoinedTimestamp in Session desktop but in seconds rather than MS }; - export type LegacyGroupInfo = BaseGroupInfo & { + export type LegacyGroupInfo = BaseUserGroup & { pubkeyHex: string; // The legacy group "session id" (33 bytes). name: string; // human-readable; this should normally always be set, but in theory could be set to an empty string. encPubkey: Uint8Array; // bytes (32 or empty) @@ -38,11 +38,19 @@ declare module 'libsession_util_nodejs' { members: Array; }; - export type CreateGroupResult = BaseGroupInfo & { + type UserGroupsGet = BaseUserGroup & { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. - secretKey: FixedSizeUint8Array<64>; + secretKey: FixedSizeUint8Array<64> | null; + authData: Uint8Array | null; }; + /** + * We can set anything on a UserGroup and can omit fields by explicitely setting them to null. + * The only one which cannot be omited is the pubkeyHex + */ + type UserGroupsSet = Pick & + AllFieldsNullable>; + type UserGroupsWrapper = BaseConfigWrapper & { init: (secretKey: Uint8Array, dump: Uint8Array | null) => void; @@ -70,11 +78,12 @@ declare module 'libsession_util_nodejs' { eraseLegacyGroup: (pubkeyHex: string) => boolean; // Groups related methods - createGroup: () => CreateGroupResult; - getGroup: (pubkeyHex: GroupPubkeyType) => GroupInfoGet | null; - // getAllGroups: () => Array; - // setGroup: (info: LegacyGroupInfo) => boolean; - // eraseGroup: (pubkeyHex: GroupPubkeyType) => boolean; + // the create group always returns the secretKey as we've just created it + createGroup: () => UserGroupsGet & NonNullable>; + getGroup: (pubkeyHex: GroupPubkeyType) => UserGroupsGet | null; + getAllGroups: () => Array; + setGroup: (info: UserGroupsSet) => UserGroupsGet; + eraseGroup: (pubkeyHex: GroupPubkeyType) => boolean; }; export type UserGroupsWrapperActionsCalls = MakeWrapperActionCalls; @@ -97,9 +106,9 @@ declare module 'libsession_util_nodejs' { // groups related methods public createGroup: UserGroupsWrapper['createGroup']; public getGroup: UserGroupsWrapper['getGroup']; - // public getAllGroups: UserGroupsWrapper['getAllGroups']; - // public setGroup: UserGroupsWrapper['setGroup']; - // public eraseGroup: UserGroupsWrapper['eraseGroup']; + public getAllGroups: UserGroupsWrapper['getAllGroups']; + public setGroup: UserGroupsWrapper['setGroup']; + public eraseGroup: UserGroupsWrapper['eraseGroup']; } export type UserGroupsConfigActionsType = @@ -114,5 +123,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall; } From e8060f3d8df81f293c4038ee3e45a6251cc94365 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 14 Sep 2023 14:22:34 +1000 Subject: [PATCH 12/64] feat: add metaMerge for group wrapper --- libsession-util | 2 +- src/base_config.cpp | 17 +-- src/base_config.hpp | 3 - src/groups/meta_group_wrapper.cpp | 187 +++++++++++++++++++++++++++--- src/groups/meta_group_wrapper.hpp | 39 ++++--- src/utilities.cpp | 28 +++++ src/utilities.hpp | 23 ++++ types/groups/metagroup.d.ts | 30 ++++- types/shared.d.ts | 18 ++- types/user/usergroups.d.ts | 2 +- 10 files changed, 295 insertions(+), 54 deletions(-) diff --git a/libsession-util b/libsession-util index c272e06..9a46cd6 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit c272e06f53b08d7b6eb92d39a7ac83c44c62eb41 +Subproject commit 9a46cd63320129acc6d5074c7900a8138a857862 diff --git a/src/base_config.cpp b/src/base_config.cpp index ce4976e..44bea59 100644 --- a/src/base_config.cpp +++ b/src/base_config.cpp @@ -15,12 +15,6 @@ Napi::Value ConfigBaseImpl::needsPush(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return get_config().needs_push(); }); } -Napi::Value ConfigBaseImpl::storageNamespace(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - return static_cast(get_config().storage_namespace()); - }); -} - Napi::Value ConfigBaseImpl::currentHashes(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return (get_config().current_hashes()); }); } @@ -28,15 +22,10 @@ Napi::Value ConfigBaseImpl::currentHashes(const Napi::CallbackInfo& info) { Napi::Value ConfigBaseImpl::push(const Napi::CallbackInfo& info) { return wrapResult(info, [&]() { assertInfoLength(info, 0); - auto [seqno, to_push, hashes] = get_config().push(); - - auto env = info.Env(); - Napi::Object result = Napi::Object::New(env); - result["data"] = toJs(env, to_push); - result["seqno"] = toJs(env, seqno); - result["hashes"] = toJs(env, hashes); + auto& conf = get_config(); + auto to_push = conf.push(); - return result; + return push_entry_to_JS(info.Env(), to_push, conf.storage_namespace()); }); } diff --git a/src/base_config.hpp b/src/base_config.hpp index febda54..d11d2b8 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -33,7 +33,6 @@ class ConfigBaseImpl { // These are exposed as read-only accessors rather than methods: Napi::Value needsDump(const Napi::CallbackInfo& info); Napi::Value needsPush(const Napi::CallbackInfo& info); - Napi::Value storageNamespace(const Napi::CallbackInfo& info); Napi::Value currentHashes(const Napi::CallbackInfo& info); Napi::Value push(const Napi::CallbackInfo& info); @@ -53,9 +52,7 @@ class ConfigBaseImpl { properties.push_back(T::InstanceMethod("needsDump", &T::needsDump)); properties.push_back(T::InstanceMethod("needsPush", &T::needsPush)); - properties.push_back(T::InstanceMethod("storageNamespace", &T::storageNamespace)); properties.push_back(T::InstanceMethod("currentHashes", &T::currentHashes)); - properties.push_back(T::InstanceMethod("push", &T::push)); properties.push_back(T::InstanceMethod("dump", &T::dump)); properties.push_back(T::InstanceMethod("confirmPushed", &T::confirmPushed)); diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index ec4b7aa..6587525 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -6,16 +6,6 @@ namespace session::nodeapi { -Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry) { - auto obj = Napi::Object::New(env); - - obj["seqno"] = toJs(env, std::get<0>(push_entry)); - obj["data"] = toJs(env, std::get<1>(push_entry)); - obj["hashes"] = toJs(env, std::get<2>(push_entry)); - - return obj; -}; - MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : meta_group{MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper")}, Napi::ObjectWrap{info} {} @@ -32,6 +22,8 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("push", &MetaGroupWrapper::push), InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), InstanceMethod("metaDump", &MetaGroupWrapper::metaDump), + InstanceMethod("metaConfirmPushed", &MetaGroupWrapper::metaConfirmPushed), + InstanceMethod("metaMerge", &MetaGroupWrapper::metaMerge), // infos exposed functions InstanceMethod("infoGet", &MetaGroupWrapper::infoGet), @@ -67,10 +59,177 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { Napi::Value MetaGroupWrapper::needsPush(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - return this->meta_group->members->needs_push() || - this->meta_group->info - ->needs_push(); // || this->meta_group->keys->needs_rekey() // TODO - // see what to do with this and needs_rekey below + return this->meta_group->members->needs_push() || this->meta_group->info->needs_push() || + this->meta_group->keys->pending_config(); + }); +} + +void MetaGroupWrapper::metaConfirmPushed(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&]() { + assertInfoLength(info, 1); + auto arg = info[0]; + assertIsObject(arg); + auto obj = arg.As(); + + auto groupInfo = obj.Get("groupInfo"); + auto groupMember = obj.Get("groupMember"); + auto groupKeys = obj.Get("groupKeys"); + + // Note: we need to process keys first as they might allow us the incoming info+members + // details + if (!groupKeys.IsNull() && !groupKeys.IsUndefined()) { + assertIsArray(groupKeys); + auto groupKeysArr = groupKeys.As(); + if (groupKeysArr.Length() != 3) { + throw std::invalid_argument("groupKeysArr length was not 3"); + } + + auto data = maybeNonemptyBuffer( + groupKeysArr.Get("0"), "MetaGroupWrapper::metaConfirmPushed groupKeysArr data"); + auto hash = maybeNonemptyString( + groupKeysArr.Get("1"), "MetaGroupWrapper::metaConfirmPushed groupKeysArr hash"); + auto timestamp_ms = maybeNonemptyInt( + groupKeysArr.Get("2"), + "MetaGroupWrapper::metaConfirmPushed groupKeysArr timestamp_ms"); + if (data && hash && timestamp_ms) + this->meta_group->keys->load_key_message( + *hash, + *data, + *timestamp_ms, + *(this->meta_group->info), + *(this->meta_group->members)); + } + + if (!groupInfo.IsNull() && !groupInfo.IsUndefined()) { + assertIsArray(groupInfo); + auto groupInfoArr = groupInfo.As(); + if (groupInfoArr.Length() != 2) { + throw std::invalid_argument("groupInfoArr length was not 2"); + } + + auto seqno = maybeNonemptyInt( + groupInfoArr.Get("0"), "MetaGroupWrapper::metaConfirmPushed groupInfo seqno"); + auto hash = maybeNonemptyString( + groupInfoArr.Get("1"), "MetaGroupWrapper::metaConfirmPushed groupInfo hash"); + if (seqno && hash) + this->meta_group->info->confirm_pushed(*seqno, *hash); + } + + if (!groupMember.IsNull() && !groupMember.IsUndefined()) { + assertIsArray(groupMember); + auto groupMemberArr = groupMember.As(); + if (groupMemberArr.Length() != 2) { + throw std::invalid_argument("groupMemberArr length was not 2"); + } + + auto seqno = maybeNonemptyInt( + groupMemberArr.Get("0"), + "MetaGroupWrapper::metaConfirmPushed groupMemberArr seqno"); + auto hash = maybeNonemptyString( + groupMemberArr.Get("1"), + "MetaGroupWrapper::metaConfirmPushed groupMemberArr hash"); + if (seqno && hash) + this->meta_group->members->confirm_pushed(*seqno, *hash); + } + }); +}; + +Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + auto arg = info[0]; + assertIsObject(arg); + auto obj = arg.As(); + + auto groupInfo = obj.Get("groupInfo"); + auto groupMember = obj.Get("groupMember"); + auto groupKeys = obj.Get("groupKeys"); + + auto count_merged = 0; + + // Note: we need to process keys first as they might allow us the incoming info+members + // details + if (!groupKeys.IsNull() && !groupKeys.IsUndefined()) { + assertIsArray(groupKeys); + auto asArr = groupKeys.As(); + + for (uint32_t i = 0; i < asArr.Length(); i++) { + Napi::Value item = asArr[i]; + assertIsObject(item); + if (item.IsEmpty()) + throw std::invalid_argument("MetaMerge.item groupKeys received empty"); + + Napi::Object itemObject = item.As(); + assertIsString(itemObject.Get("hash")); + assertIsUInt8Array(itemObject.Get("data")); + assertIsNumber(itemObject.Get("timestampMs")); + + auto hash = toCppString(itemObject.Get("hash"), "meta.merge keys hash"); + auto data = toCppBuffer(itemObject.Get("data"), "meta.merge keys data"); + auto timestamp_ms = toCppInteger( + itemObject.Get("timestampMs"), "meta.merge keys timestampMs", false); + + this->meta_group->keys->load_key_message( + hash, + data, + timestamp_ms, + *(this->meta_group->info), + *(this->meta_group->members)); + count_merged++; // load_key_message doesn't necessarely merge something as not + // all keys are for us. + } + } + + if (!groupInfo.IsNull() && !groupInfo.IsUndefined()) { + assertIsArray(groupInfo); + auto asArr = groupInfo.As(); + + std::vector> conf_strs; + conf_strs.reserve(asArr.Length()); + + for (uint32_t i = 0; i < asArr.Length(); i++) { + Napi::Value item = asArr[i]; + assertIsObject(item); + if (item.IsEmpty()) + throw std::invalid_argument("MetaMerge.item groupInfo received empty"); + + Napi::Object itemObject = item.As(); + assertIsString(itemObject.Get("hash")); + assertIsUInt8Array(itemObject.Get("data")); + conf_strs.emplace_back( + toCppString(itemObject.Get("hash"), "meta.merge"), + toCppBufferView(itemObject.Get("data"), "meta.merge")); + } + + auto info_count_merged = this->meta_group->info->merge(conf_strs); + count_merged += info_count_merged; + } + + if (!groupMember.IsNull() && !groupMember.IsUndefined()) { + assertIsArray(groupMember); + auto asArr = groupMember.As(); + + std::vector> conf_strs; + conf_strs.reserve(asArr.Length()); + + for (uint32_t i = 0; i < asArr.Length(); i++) { + Napi::Value item = asArr[i]; + assertIsObject(item); + if (item.IsEmpty()) + throw std::invalid_argument("MetaMerge.item groupMember received empty"); + + Napi::Object itemObject = item.As(); + assertIsString(itemObject.Get("hash")); + assertIsUInt8Array(itemObject.Get("data")); + conf_strs.emplace_back( + toCppString(itemObject.Get("hash"), "meta.merge"), + toCppBufferView(itemObject.Get("data"), "meta.merge")); + } + + auto member_count_merged = this->meta_group->members->merge(conf_strs); + count_merged += member_count_merged; + } + return count_merged; }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index cabac03..27519ca 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -31,13 +31,6 @@ struct toJs_impl { } }; -using push_entry_t = std::tuple< - session::config::seqno_t, - session::ustring, - std::vector>>; - -Napi::Object push_entry_to_JS(const Napi::Env& env, const push_entry_t& push_entry); - class MetaGroupWrapper : public Napi::ObjectWrap { public: static void Init(Napi::Env env, Napi::Object exports); @@ -56,13 +49,28 @@ class MetaGroupWrapper : public Napi::ObjectWrap { auto env = info.Env(); auto to_push = Napi::Object::New(env); - to_push["GroupMember"s] = push_entry_to_JS(env, this->meta_group->members->push()); - to_push["GroupInfo"s] = push_entry_to_JS(env, this->meta_group->info->push()); + if (this->meta_group->members->needs_push()) + to_push["groupMember"s] = push_entry_to_JS( + env, + this->meta_group->members->push(), + this->meta_group->members->storage_namespace()); + else + to_push["groupMember"s] = env.Null(); + + if (this->meta_group->info->needs_push()) + to_push["groupInfo"s] = push_entry_to_JS( + env, + this->meta_group->info->push(), + this->meta_group->info->storage_namespace()); + else + to_push["groupInfo"s] = env.Null(); + + if (auto pending_config = this->meta_group->keys->pending_config()) + to_push["groupKeys"s] = push_key_entry_to_JS( + env, *(pending_config), this->meta_group->keys->storage_namespace()); + else + to_push["groupKeys"s] = env.Null(); - // TODO see what to do with this and needs_rekey below? - // to_push.push_back(std::make_pair("GroupKeys"s, - // this->meta_group->keys_rekey())); - // } return to_push; }); } @@ -87,10 +95,13 @@ class MetaGroupWrapper : public Napi::ObjectWrap { "members", session::from_unsigned_sv(this->meta_group->members->dump())); auto to_dump = std::move(combined).str(); - return to_unsigned_sv(to_dump); + return ustring{to_unsigned_sv(to_dump)}; }); } + void metaConfirmPushed(const Napi::CallbackInfo& info); + Napi::Value metaMerge(const Napi::CallbackInfo& info); + /** Info Actions */ Napi::Value infoGet(const Napi::CallbackInfo& info); diff --git a/src/utilities.cpp b/src/utilities.cpp index 018d19f..992d6d2 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -2,6 +2,8 @@ #include +#include "session/config/namespaces.hpp" + namespace session::nodeapi { static void checkOrThrow(bool condition, const char* msg) { @@ -179,4 +181,30 @@ int64_t unix_timestamp_now() { return duration_cast(system_clock::now().time_since_epoch()).count(); } +Napi::Object push_entry_to_JS( + const Napi::Env& env, + const push_entry_t& push_entry, + const session::config::Namespace& push_namespace) { + auto obj = Napi::Object::New(env); + + obj["seqno"] = toJs(env, std::get<0>(push_entry)); + obj["data"] = toJs(env, std::get<1>(push_entry)); + obj["hashes"] = toJs(env, std::get<2>(push_entry)); + obj["namespace"] = toJs(env, push_namespace); + + return obj; +}; + +Napi::Object push_key_entry_to_JS( + const Napi::Env& env, + const session::ustring_view& key_data, + const session::config::Namespace& push_namespace) { + auto obj = Napi::Object::New(env); + + obj["data"] = toJs(env, key_data); + obj["namespace"] = toJs(env, push_namespace); + + return obj; +}; + } // namespace session::nodeapi diff --git a/src/utilities.hpp b/src/utilities.hpp index feddb23..00f1b2b 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -8,6 +8,7 @@ #include #include +#include "session/config/namespaces.hpp" #include "session/types.hpp" #include "utilities.hpp" @@ -96,6 +97,13 @@ template <> struct toJs_impl { auto operator()(const Napi::Env& env, bool b) const { return Napi::Boolean::New(env, b); } }; +template <> +struct toJs_impl { + auto operator()(const Napi::Env& env, session::config::Namespace b) const { + return Napi::Number::New(env, static_cast(b)); + } +}; + template struct toJs_impl>> { auto operator()(const Napi::Env& env, T n) const { return Napi::Number::New(env, n); } @@ -234,4 +242,19 @@ int64_t toPriority(Napi::Value x, int64_t currentPriority); int64_t unix_timestamp_now(); +using push_entry_t = std::tuple< + session::config::seqno_t, + session::ustring, + std::vector>>; + +Napi::Object push_entry_to_JS( + const Napi::Env& env, + const push_entry_t& push_entry, + const session::config::Namespace& push_namespace); + +Napi::Object push_key_entry_to_JS( + const Napi::Env& env, + const session::ustring_view& key_data, + const session::config::Namespace& push_namespace); + } // namespace session::nodeapi diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index d860967..ad26eb3 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -4,6 +4,8 @@ /// declare module 'libsession_util_nodejs' { + export type ConfirmKeysPush = [data: Uint8Array, hash: string, timestampMs: number]; + export type GroupWrapperConstructor = { userEd25519Secretkey: FixedSizeUint8Array<64>; groupEd25519Pubkey: FixedSizeUint8Array<32>; // the ed25519 pubkey without the 03 prefix @@ -17,9 +19,31 @@ declare module 'libsession_util_nodejs' { // shared actions init: (options: GroupWrapperConstructor) => void; needsPush: () => boolean; - push: () => { [T in Exclude]: PushConfigResult }; // GroupKeys push comes from rekey() and has no hashes etc associated. + push: () => { + groupInfo: PushConfigResult | null; + groupMember: PushConfigResult | null; + groupKeys: PushKeyConfigResult | null; + }; needsDump: () => boolean; metaDump: () => Uint8Array; + metaConfirmPushed: ({ + groupInfo, + groupKeys, + groupMember, + }: { + groupInfo: ConfirmPush | null; + groupMember: ConfirmPush | null; + groupKeys: ConfirmKeysPush | null; + }) => void; + metaMerge: ({ + groupInfo, + groupKeys, + groupMember, + }: { + groupInfo: Array | null; + groupMember: Array | null; + groupKeys: Array | null; + }) => void; }; // this just adds an argument of type GroupPubkeyType in front of the parameters of that function @@ -39,6 +63,8 @@ declare module 'libsession_util_nodejs' { public push: MetaGroupWrapper['push']; public needsDump: MetaGroupWrapper['needsDump']; public metaDump: MetaGroupWrapper['metaDump']; + public metaConfirmPushed: MetaGroupWrapper['metaConfirmPushed']; + public metaMerge: MetaGroupWrapper['metaMerge']; // info public infoGet: MetaGroupWrapper['infoGet']; @@ -74,6 +100,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall + | MakeActionCall // info actions | MakeActionCall diff --git a/types/shared.d.ts b/types/shared.d.ts index 12a4682..aec8c6a 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -44,7 +44,17 @@ declare module 'libsession_util_nodejs' { key: Uint8Array | null; }; - export type PushConfigResult = { data: Uint8Array; seqno: number; hashes: Array }; + export type PushConfigResult = { + data: Uint8Array; + seqno: number; + hashes: Array; + namespace: number; + }; + + export type PushKeyConfigResult = Pick; + + export type ConfirmPush = [seqno: number, hash: string]; + export type MergeSingle = { hash: string; data: Uint8Array }; type MakeActionCall = [B, ...Parameters]; @@ -60,8 +70,7 @@ declare module 'libsession_util_nodejs' { push: () => PushConfigResult; dump: () => Uint8Array; confirmPushed: (seqno: number, hash: string) => void; - merge: (toMerge: Array<{ hash: string; data: Uint8Array }>) => number; - storageNamespace: () => number; + merge: (toMerge: Array) => number; currentHashes: () => Array; }; @@ -73,7 +82,6 @@ declare module 'libsession_util_nodejs' { | 'confirmPushed' | 'merge' | 'needsPush' - | 'storageNamespace' | 'currentHashes'; export type GenericWrapperActionsCall = ( @@ -88,7 +96,6 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall | MakeActionCall; export abstract class BaseConfigWrapperNode { @@ -98,7 +105,6 @@ declare module 'libsession_util_nodejs' { public dump: BaseConfigWrapper['dump']; public confirmPushed: BaseConfigWrapper['confirmPushed']; public merge: BaseConfigWrapper['merge']; - public storageNamespace: BaseConfigWrapper['storageNamespace']; public currentHashes: BaseConfigWrapper['currentHashes']; } diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 36656c8..77b0864 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -7,7 +7,7 @@ declare module 'libsession_util_nodejs' { * */ - export type UserGroupsType = 'Community' | 'LegacyGroup'; + export type UserGroupsType = 'Community' | 'LegacyGroup' | 'Group'; export type CommunityDetails = { fullUrlWithPubkey: string; From d03e55d7de7e5a1014a0cd40521b11e2bd433251 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 15 Sep 2023 16:35:00 +1000 Subject: [PATCH 13/64] feat: add a type for 05 pubkeys and blinded ones --- types/shared.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/shared.d.ts b/types/shared.d.ts index aec8c6a..45a5411 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -111,6 +111,8 @@ declare module 'libsession_util_nodejs' { export type BaseWrapperActionsCalls = MakeWrapperActionCalls; export type GroupPubkeyType = `03${string}`; // type of a string which starts by the 03 prefixed used for closed group + export type PubkeyType = `05${string}`; // type of a string which starts by the 05 prefixed used for **legacy** closed group and session ids + export type BlindedPubkeyType = `15${string}`; type MakeGroupActionCall = [ B, From 02021c162f5bce6e859fe440088da1feeccb4630 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 18 Sep 2023 10:04:41 +1000 Subject: [PATCH 14/64] fix: do not confirmKeys when pushed. wait for poll event --- src/groups/meta_group_wrapper.cpp | 25 ------------------------- types/groups/metagroup.d.ts | 2 -- 2 files changed, 27 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 6587525..9d9010f 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -75,31 +75,6 @@ void MetaGroupWrapper::metaConfirmPushed(const Napi::CallbackInfo& info) { auto groupMember = obj.Get("groupMember"); auto groupKeys = obj.Get("groupKeys"); - // Note: we need to process keys first as they might allow us the incoming info+members - // details - if (!groupKeys.IsNull() && !groupKeys.IsUndefined()) { - assertIsArray(groupKeys); - auto groupKeysArr = groupKeys.As(); - if (groupKeysArr.Length() != 3) { - throw std::invalid_argument("groupKeysArr length was not 3"); - } - - auto data = maybeNonemptyBuffer( - groupKeysArr.Get("0"), "MetaGroupWrapper::metaConfirmPushed groupKeysArr data"); - auto hash = maybeNonemptyString( - groupKeysArr.Get("1"), "MetaGroupWrapper::metaConfirmPushed groupKeysArr hash"); - auto timestamp_ms = maybeNonemptyInt( - groupKeysArr.Get("2"), - "MetaGroupWrapper::metaConfirmPushed groupKeysArr timestamp_ms"); - if (data && hash && timestamp_ms) - this->meta_group->keys->load_key_message( - *hash, - *data, - *timestamp_ms, - *(this->meta_group->info), - *(this->meta_group->members)); - } - if (!groupInfo.IsNull() && !groupInfo.IsUndefined()) { assertIsArray(groupInfo); auto groupInfoArr = groupInfo.As(); diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index ad26eb3..1cbab12 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -28,12 +28,10 @@ declare module 'libsession_util_nodejs' { metaDump: () => Uint8Array; metaConfirmPushed: ({ groupInfo, - groupKeys, groupMember, }: { groupInfo: ConfirmPush | null; groupMember: ConfirmPush | null; - groupKeys: ConfirmKeysPush | null; }) => void; metaMerge: ({ groupInfo, From 9534f51be9d1328e5eb3896c22fab526b4f23a24 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 21 Sep 2023 15:46:54 +1000 Subject: [PATCH 15/64] feat: add encrypt/decrypt and expose make_dump --- src/groups/meta_group_wrapper.cpp | 2 +- src/groups/meta_group_wrapper.hpp | 28 ++++++++++++++++++++++------ src/user_groups_config.cpp | 6 ++++++ src/utilities.cpp | 12 +++++++++++- src/utilities.hpp | 3 +++ types/groups/groupinfo.d.ts | 2 +- types/groups/groupkeys.d.ts | 4 ++-- types/groups/metagroup.d.ts | 3 +++ types/shared.d.ts | 1 - types/user/usergroups.d.ts | 1 + 10 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 9d9010f..9b315ea 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -22,6 +22,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("push", &MetaGroupWrapper::push), InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), InstanceMethod("metaDump", &MetaGroupWrapper::metaDump), + InstanceMethod("metaDebugDump", &MetaGroupWrapper::metaDebugDump), InstanceMethod("metaConfirmPushed", &MetaGroupWrapper::metaConfirmPushed), InstanceMethod("metaMerge", &MetaGroupWrapper::metaMerge), @@ -52,7 +53,6 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), - }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 27519ca..a50bff8 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -99,6 +99,23 @@ class MetaGroupWrapper : public Napi::ObjectWrap { }); } + Napi::Value metaDebugDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + + oxenc::bt_dict_producer combined; + + // NB: the keys have to be in ascii-sorted order: + combined.append("info", session::from_unsigned_sv(this->meta_group->info->make_dump())); + combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->make_dump())); + combined.append( + "members", session::from_unsigned_sv(this->meta_group->members->make_dump())); + auto to_dump = std::move(combined).str(); + + return ustring{to_unsigned_sv(to_dump)}; + }); + } + void metaConfirmPushed(const Napi::CallbackInfo& info); Napi::Value metaMerge(const Napi::CallbackInfo& info); @@ -278,13 +295,10 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value encryptMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsUInt8Array(info[0]); - assertIsBoolean(info[1]); + assertInfoLength(info, 1); auto plaintext = toCppBuffer(info[0], __PRETTY_FUNCTION__); - auto compress = toCppBoolean(info[1], __PRETTY_FUNCTION__); - return this->meta_group->keys->encrypt_message(plaintext, compress); + return this->meta_group->keys->encrypt_message(plaintext); }); } Napi::Value decryptMessage(const Napi::CallbackInfo& info) { @@ -293,7 +307,9 @@ class MetaGroupWrapper : public Napi::ObjectWrap { assertIsUInt8Array(info[0]); auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); - return this->meta_group->keys->decrypt_message(ciphertext); + auto decrypted = this->meta_group->keys->decrypt_message(ciphertext); + + return decrypt_result_to_JS(info.Env(), decrypted); }); } }; diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index a2df062..39ce40c 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -66,6 +66,8 @@ struct toJs_impl { obj["secretKey"] = toJs(env, info.secretkey); obj["priority"] = toJs(env, info.priority); obj["joinedAtSeconds"] = toJs(env, info.joined_at); + obj["name"] = toJs(env, info.name); + // TODO kicked and setKicked todo return obj; } @@ -316,6 +318,10 @@ Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { group_info.auth_data = *authData; } + if (auto name = maybeNonemptyString(obj.Get("name"), "UserGroupsWrapper::setGroup name")) { + group_info.name = *name; + } + config.set(group_info); return config.get_or_construct_group(groupPk); diff --git a/src/utilities.cpp b/src/utilities.cpp index 992d6d2..8245b88 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -181,7 +181,7 @@ int64_t unix_timestamp_now() { return duration_cast(system_clock::now().time_since_epoch()).count(); } -Napi::Object push_entry_to_JS( +Napi::Object push_result_to_JS( const Napi::Env& env, const push_entry_t& push_entry, const session::config::Namespace& push_namespace) { @@ -207,4 +207,14 @@ Napi::Object push_key_entry_to_JS( return obj; }; +Napi::Object decrypt_result_to_JS( + const Napi::Env& env, const std::pair decrypted) { + auto obj = Napi::Object::New(env); + + obj["pubkeyHex"] = toJs(env, decrypted.first); + obj["plaintext"] = toJs(env, decrypted.second); + + return obj; +} + } // namespace session::nodeapi diff --git a/src/utilities.hpp b/src/utilities.hpp index 00f1b2b..80d6fe4 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -257,4 +257,7 @@ Napi::Object push_key_entry_to_JS( const session::ustring_view& key_data, const session::config::Namespace& push_namespace); +Napi::Object decrypt_result_to_JS( + const Napi::Env& env, const std::pair decrypted); + } // namespace session::nodeapi diff --git a/types/groups/groupinfo.d.ts b/types/groups/groupinfo.d.ts index 54bee88..052e3c2 100644 --- a/types/groups/groupinfo.d.ts +++ b/types/groups/groupinfo.d.ts @@ -8,7 +8,7 @@ declare module 'libsession_util_nodejs' { export type GroupInfoWrapper = { // GroupInfo related methods - infoGet: () => GroupInfoGet | null; + infoGet: () => GroupInfoGet; infoSet: (info: GroupInfoSet) => GroupInfoGet; infoDestroy: () => void; }; diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 2825b00..f5ee96e 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -9,7 +9,7 @@ declare module 'libsession_util_nodejs' { loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; currentHashes: () => Array; - encryptMessage: (plaintext: Uint8Array, compress: boolean) => Uint8Array; - decryptMessage: (ciphertext: Uint8Array) => Uint8Array | null; + encryptMessage: (plaintext: Uint8Array) => Uint8Array; + decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; }; } diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 1cbab12..0d88936 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -26,6 +26,7 @@ declare module 'libsession_util_nodejs' { }; needsDump: () => boolean; metaDump: () => Uint8Array; + metaDebugDump: () => Uint8Array; metaConfirmPushed: ({ groupInfo, groupMember, @@ -61,6 +62,7 @@ declare module 'libsession_util_nodejs' { public push: MetaGroupWrapper['push']; public needsDump: MetaGroupWrapper['needsDump']; public metaDump: MetaGroupWrapper['metaDump']; + public metaDebugDump: MetaGroupWrapper['metaDebugDump']; public metaConfirmPushed: MetaGroupWrapper['metaConfirmPushed']; public metaMerge: MetaGroupWrapper['metaMerge']; @@ -98,6 +100,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall diff --git a/types/shared.d.ts b/types/shared.d.ts index 45a5411..5f1f52b 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -129,7 +129,6 @@ declare module 'libsession_util_nodejs' { }; export type PriorityType = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned - type GroupSubWrapperType = 'GroupInfo' | 'GroupMember' | 'GroupKeys'; type GroupInfoShared = { name: string | null; diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 77b0864..8989ef2 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -42,6 +42,7 @@ declare module 'libsession_util_nodejs' { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. secretKey: FixedSizeUint8Array<64> | null; authData: Uint8Array | null; + name: string | null; }; /** From 05606d5b9bf7b05db7cd9b45dacd93bfa3d25ad7 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 3 Oct 2023 11:52:49 +1100 Subject: [PATCH 16/64] fix: compile issues and bump libsession-util --- CMakeLists.txt | 2 +- libsession-util | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da0c432..22960c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC}) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC} "node_modules/node-addon-api" "../../node_modules/node-addon-api") set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node") -target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB} libsession::config libsession::crypto) +target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB} ${LIBSESSION_STATIC_BUNDLE_LIBS}) if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET) # Generate node.lib diff --git a/libsession-util b/libsession-util index 9a46cd6..cda4d32 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 9a46cd63320129acc6d5074c7900a8138a857862 +Subproject commit cda4d32e2672e9f8dd4ca1822b0cc3e0c5005497 From d51297fe7735063e4ffcb76d1591096a1cfa050b Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 9 Oct 2023 17:08:25 +1100 Subject: [PATCH 17/64] fix: linking error and remove groupKeys function for now --- src/base_config.cpp | 2 +- src/groups/meta_group_wrapper.hpp | 4 ++-- src/utilities.hpp | 2 +- types/groups/groupkeys.d.ts | 4 +--- types/groups/metagroup.d.ts | 4 +--- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/base_config.cpp b/src/base_config.cpp index 44bea59..869da11 100644 --- a/src/base_config.cpp +++ b/src/base_config.cpp @@ -25,7 +25,7 @@ Napi::Value ConfigBaseImpl::push(const Napi::CallbackInfo& info) { auto& conf = get_config(); auto to_push = conf.push(); - return push_entry_to_JS(info.Env(), to_push, conf.storage_namespace()); + return push_result_to_JS(info.Env(), to_push, conf.storage_namespace()); }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index a50bff8..c6540a4 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -50,7 +50,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { auto to_push = Napi::Object::New(env); if (this->meta_group->members->needs_push()) - to_push["groupMember"s] = push_entry_to_JS( + to_push["groupMember"s] = push_result_to_JS( env, this->meta_group->members->push(), this->meta_group->members->storage_namespace()); @@ -58,7 +58,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { to_push["groupMember"s] = env.Null(); if (this->meta_group->info->needs_push()) - to_push["groupInfo"s] = push_entry_to_JS( + to_push["groupInfo"s] = push_result_to_JS( env, this->meta_group->info->push(), this->meta_group->info->storage_namespace()); diff --git a/src/utilities.hpp b/src/utilities.hpp index 80d6fe4..ea0240e 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -247,7 +247,7 @@ using push_entry_t = std::tuple< session::ustring, std::vector>>; -Napi::Object push_entry_to_JS( +Napi::Object push_result_to_JS( const Napi::Env& env, const push_entry_t& push_entry, const session::config::Namespace& push_namespace); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index f5ee96e..d047152 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -4,11 +4,9 @@ declare module 'libsession_util_nodejs' { export type GroupKeysWrapper = { keysNeedsRekey: () => boolean; keyRekey: () => Uint8Array; - groupKeys: () => Array; - loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; - currentHashes: () => Array; + currentHashes: () => Array; encryptMessage: (plaintext: Uint8Array) => Uint8Array; decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; }; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 0d88936..728f62c 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -65,6 +65,7 @@ declare module 'libsession_util_nodejs' { public metaDebugDump: MetaGroupWrapper['metaDebugDump']; public metaConfirmPushed: MetaGroupWrapper['metaConfirmPushed']; public metaMerge: MetaGroupWrapper['metaMerge']; + public currentHashes: MetaGroupWrapper['currentHashes']; // info public infoGet: MetaGroupWrapper['infoGet']; @@ -86,9 +87,7 @@ declare module 'libsession_util_nodejs' { public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; public keyRekey: MetaGroupWrapper['keyRekey']; - public groupKeys: MetaGroupWrapper['groupKeys']; public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; - public currentHashes: MetaGroupWrapper['currentHashes']; public encryptMessage: MetaGroupWrapper['encryptMessage']; public decryptMessage: MetaGroupWrapper['decryptMessage']; } @@ -123,7 +122,6 @@ declare module 'libsession_util_nodejs' { // keys actions | MakeActionCall | MakeActionCall - | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall From 363e21dc5e4e127b10a4c2b2ed17cd6cf71e09aa Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 9 Oct 2023 17:43:19 +1100 Subject: [PATCH 18/64] chore: pull protobuf branch --- libsession-util | 2 +- src/groups/meta_group_wrapper.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libsession-util b/libsession-util index cda4d32..6c4e38c 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit cda4d32e2672e9f8dd4ca1822b0cc3e0c5005497 +Subproject commit 6c4e38c4ed7f3a153428491bda588c782f8e0c60 diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 9b315ea..6941e15 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -176,8 +176,8 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { toCppBufferView(itemObject.Get("data"), "meta.merge")); } - auto info_count_merged = this->meta_group->info->merge(conf_strs); - count_merged += info_count_merged; + auto info_merged = this->meta_group->info->merge(conf_strs); + count_merged += info_merged.size(); } if (!groupMember.IsNull() && !groupMember.IsUndefined()) { @@ -201,8 +201,9 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { toCppBufferView(itemObject.Get("data"), "meta.merge")); } - auto member_count_merged = this->meta_group->members->merge(conf_strs); - count_merged += member_count_merged; + auto member_merged = this->meta_group->members->merge(conf_strs); + + count_merged += member_merged.size(); } return count_merged; }); From 097e2d28ed45fe55e34319a9750277e0204d515f Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 10 Oct 2023 14:41:07 +1100 Subject: [PATCH 19/64] feat: add makeDump function to configBase calls too --- src/base_config.cpp | 7 +++++++ src/base_config.hpp | 2 ++ src/groups/meta_group_wrapper.cpp | 2 +- src/groups/meta_group_wrapper.hpp | 2 +- types/groups/metagroup.d.ts | 6 +++--- types/shared.d.ts | 4 ++++ 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/base_config.cpp b/src/base_config.cpp index 869da11..45314fd 100644 --- a/src/base_config.cpp +++ b/src/base_config.cpp @@ -36,6 +36,13 @@ Napi::Value ConfigBaseImpl::dump(const Napi::CallbackInfo& info) { }); } +Napi::Value ConfigBaseImpl::makeDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&]() { + assertInfoLength(info, 0); + return get_config().make_dump(); + }); +} + void ConfigBaseImpl::confirmPushed(const Napi::CallbackInfo& info) { return wrapResult(info, [&]() { assertInfoLength(info, 2); diff --git a/src/base_config.hpp b/src/base_config.hpp index d11d2b8..9f41718 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -37,6 +37,7 @@ class ConfigBaseImpl { Napi::Value push(const Napi::CallbackInfo& info); Napi::Value dump(const Napi::CallbackInfo& info); + Napi::Value makeDump(const Napi::CallbackInfo& info); void confirmPushed(const Napi::CallbackInfo& info); Napi::Value merge(const Napi::CallbackInfo& info); @@ -55,6 +56,7 @@ class ConfigBaseImpl { properties.push_back(T::InstanceMethod("currentHashes", &T::currentHashes)); properties.push_back(T::InstanceMethod("push", &T::push)); properties.push_back(T::InstanceMethod("dump", &T::dump)); + properties.push_back(T::InstanceMethod("makeDump", &T::makeDump)); properties.push_back(T::InstanceMethod("confirmPushed", &T::confirmPushed)); properties.push_back(T::InstanceMethod("merge", &T::merge)); diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 6941e15..46dbce8 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -22,7 +22,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("push", &MetaGroupWrapper::push), InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), InstanceMethod("metaDump", &MetaGroupWrapper::metaDump), - InstanceMethod("metaDebugDump", &MetaGroupWrapper::metaDebugDump), + InstanceMethod("metaMakeDump", &MetaGroupWrapper::metaMakeDump), InstanceMethod("metaConfirmPushed", &MetaGroupWrapper::metaConfirmPushed), InstanceMethod("metaMerge", &MetaGroupWrapper::metaMerge), diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index c6540a4..ffc4e54 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -99,7 +99,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { }); } - Napi::Value metaDebugDump(const Napi::CallbackInfo& info) { + Napi::Value metaMakeDump(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { auto env = info.Env(); diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 728f62c..d23aefc 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -26,7 +26,7 @@ declare module 'libsession_util_nodejs' { }; needsDump: () => boolean; metaDump: () => Uint8Array; - metaDebugDump: () => Uint8Array; + metaMakeDump: () => Uint8Array; metaConfirmPushed: ({ groupInfo, groupMember, @@ -62,7 +62,7 @@ declare module 'libsession_util_nodejs' { public push: MetaGroupWrapper['push']; public needsDump: MetaGroupWrapper['needsDump']; public metaDump: MetaGroupWrapper['metaDump']; - public metaDebugDump: MetaGroupWrapper['metaDebugDump']; + public metaMakeDump: MetaGroupWrapper['metaMakeDump']; public metaConfirmPushed: MetaGroupWrapper['metaConfirmPushed']; public metaMerge: MetaGroupWrapper['metaMerge']; public currentHashes: MetaGroupWrapper['currentHashes']; @@ -99,7 +99,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall diff --git a/types/shared.d.ts b/types/shared.d.ts index 5f1f52b..0d33a4b 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -69,6 +69,7 @@ declare module 'libsession_util_nodejs' { needsPush: () => boolean; push: () => PushConfigResult; dump: () => Uint8Array; + makeDump: () => Uint8Array; confirmPushed: (seqno: number, hash: string) => void; merge: (toMerge: Array) => number; currentHashes: () => Array; @@ -79,6 +80,7 @@ declare module 'libsession_util_nodejs' { | 'needsPush' | 'push' | 'dump' + | 'makeDump' | 'confirmPushed' | 'merge' | 'needsPush' @@ -94,6 +96,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall; @@ -103,6 +106,7 @@ declare module 'libsession_util_nodejs' { public needsPush: BaseConfigWrapper['needsPush']; public push: BaseConfigWrapper['push']; public dump: BaseConfigWrapper['dump']; + public makeDump: BaseConfigWrapper['makeDump']; public confirmPushed: BaseConfigWrapper['confirmPushed']; public merge: BaseConfigWrapper['merge']; public currentHashes: BaseConfigWrapper['currentHashes']; From d1b757945c7540cd369a183e7ea9a532416d9340 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 10 Oct 2023 14:41:29 +1100 Subject: [PATCH 20/64] feat: libsession merge returns vector of hashes merged now --- types/shared.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/shared.d.ts b/types/shared.d.ts index 0d33a4b..b0aae80 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -71,7 +71,7 @@ declare module 'libsession_util_nodejs' { dump: () => Uint8Array; makeDump: () => Uint8Array; confirmPushed: (seqno: number, hash: string) => void; - merge: (toMerge: Array) => number; + merge: (toMerge: Array) => Array; // merge returns the array of hashes merged correctly currentHashes: () => Array; }; From dfa737a0c2270219c8291742e49a757c196aac87 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 13 Oct 2023 13:46:28 +1100 Subject: [PATCH 21/64] fix: no point of having a shared_ptr for the meta_group --- src/groups/meta_group_wrapper.cpp | 2 +- src/groups/meta_group_wrapper.hpp | 2 +- src/meta/meta_base_wrapper.hpp | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 46dbce8..45acfef 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -7,7 +7,7 @@ namespace session::nodeapi { MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : - meta_group{MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper")}, + meta_group{std::move(MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper"))}, Napi::ObjectWrap{info} {} void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index ffc4e54..afc1e7e 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -38,7 +38,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { explicit MetaGroupWrapper(const Napi::CallbackInfo& info); private: - std::shared_ptr meta_group; + std::unique_ptr meta_group; /* Shared Actions */ diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 26a4859..a18bea6 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -31,7 +31,7 @@ class MetaBaseWrapper { exports.Set(class_name, cls); } - static std::shared_ptr constructGroupWrapper( + static std::unique_ptr constructGroupWrapper( const Napi::CallbackInfo& info, const std::string& class_name) { return wrapExceptions(info, [&] { if (!info.IsConstructCall()) @@ -85,6 +85,8 @@ class MetaBaseWrapper { dumped_members = session::to_unsigned_sv(combined.consume_string_view()); } + // Note, we keep shared_ptr for those as the Keys one need a reference to Members and + // Info on his own currently. auto info = std::make_shared( group_ed25519_pubkey, group_ed25519_secretkey, dumped_info); @@ -99,7 +101,7 @@ class MetaBaseWrapper { *info, *members); - return std::make_shared(info, members, keys); + return std::make_unique(info, members, keys); }); } }; From 60eb5d8b9207d1fb6523697501e53f250467e0b8 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 13 Oct 2023 14:25:32 +1100 Subject: [PATCH 22/64] remove: removed unused configsig file --- src/config_sig.hpp | 131 --------------------------------------------- 1 file changed, 131 deletions(-) delete mode 100644 src/config_sig.hpp diff --git a/src/config_sig.hpp b/src/config_sig.hpp deleted file mode 100644 index db02ac4..0000000 --- a/src/config_sig.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include - -#include "session/config/base.hpp" -#include "session/types.hpp" -#include "utilities.hpp" - -using ustring_view = std::basic_string_view; - -namespace session::nodeapi { - -class ConfigSigImpl; -template -inline constexpr bool is_derived_napi_wrapper = - std::is_base_of_v&& std::is_base_of_v, T>; - -/// Base implementation class for config types; this provides the napi wrappers for the base -/// methods. Subclasses should inherit from this (alongside Napi::ObjectWrap) -/// and wrap their method list argument in `DefineClass` with a call to -/// `ConfigSigImpl::WithBaseMethods({...})` to have the base methods added to the derived -/// type appropriately. -class ConfigSigImpl { - std::shared_ptr conf_; - - public: - // Called from a sub-type's Init function (typically indirectly, via InitHelper) to add the base - // class properties/methods to the type. - template , int> = 0> - static std::vector WithBaseMethods( - std::vector properties) { - std::unordered_set seen; - for (const napi_property_descriptor& prop : properties) - if (prop.utf8name) - seen.emplace(prop.utf8name); - - return properties; - } - - protected: - // Constructor (callable from a subclass): the wrapper subclass constructs its - // ConfigSig-derived shared_ptr during *its* construction, passing it here. - ConfigSigImpl(std::shared_ptr conf) : conf_{std::move(conf)} { - if (!conf_) - throw std::invalid_argument{ - "ConfigSigImpl initialization requires a live ConfigSig pointer"}; - } - - // Constructs a shared_ptr of some config::ConfigBase-derived type, taking a secret key and - // optional dump. This is what most Config types require, but a subclass could replace this if - // it needs to do something else. - template < - typename Config, - std::enable_if_t, int> = 0> - static std::shared_ptr constructFromKeys( - const Napi::CallbackInfo& info, const std::string& class_name) { - return wrapExceptions(info, [&] { - if (!info.IsConstructCall()) - throw std::invalid_argument{ - "You need to call the constructor with the `new` syntax"}; - - assertInfoLength(info, 6); - - // types come from constructor of Keys::Keys - assertIsUInt8Array(info[0]); // user_ed25519_secretkey - assertIsUInt8Array(info[1]); // group_ed25519_pubkey - assertIsUInt8ArrayOrNull(info[2]); // group_ed25519_secretkey - assertIsUInt8ArrayOrNull(info[3]); // dumped - assertIsUInt8ArrayOrNull(info[4]); // dumped - assertIsUInt8ArrayOrNull(info[5]); // dumped - - std::string ed25519_pubkey_str = toCppString(info[0], class_name + ".new.pubkey"); - std::optional secret_key; - auto second = info[1]; - if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) - secret_key = toCppBufferView(second, class_name + ".new.secret"); - - std::optional dump; - auto third = info[2]; - if (!third.IsEmpty() && !third.IsNull() && !third.IsUndefined()) - dump = toCppBufferView(third, class_name + ".new.dump"); - - auto withoutPrefix = ed25519_pubkey_str.substr(2); - ustring ed25519_pubkey = (const unsigned char*)oxenc::from_hex(withoutPrefix).c_str(); - return std::make_shared(ed25519_pubkey, secret_key, dump); - }); - } - - virtual ~ConfigSigImpl() = default; - - // Accesses a reference the stored config instance as `std::shared_ptr` (if no template is - // specified then as the base ConfigSig type). `T` must be a subclass of ConfigSig for this - // to compile. Throws std::logic_error if not set. Throws std::invalid_argument if the - // instance is not castable to a `T`. - template , int> = 0> - T& get_config() { - assert(conf_); // should not be possible to construct without this set - if (auto* t = dynamic_cast(conf_.get())) - return *t; - throw std::invalid_argument{ - "Error retrieving config: config instance is not of the requested type"}; - } - - // Helper function for doing the subtype napi Init call. This sets up the class registration, - // sets it in the exports, and appends the base methods and properties (needsDump, etc.) to the - // given methods/properties list. - template , int> = 0> - static void InitHelper( - Napi::Env env, - Napi::Object exports, - const char* class_name, - std::vector properties) { - - Napi::Function cls = - T::DefineClass(env, class_name, WithBaseMethods(std::move(properties))); - - auto ref = std::make_unique(); - *ref = Napi::Persistent(cls); - env.SetInstanceData(ref.release()); - - exports.Set(class_name, cls); - } -}; - -} // namespace session::nodeapi From 9d2697c4ea6b934af89405aa37f208ca9083e101 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 19 Oct 2023 10:53:36 +1100 Subject: [PATCH 23/64] chore: address pr reviews --- src/groups/meta_group_wrapper.cpp | 267 ++++++++++++++++++++++++++++ src/groups/meta_group_wrapper.hpp | 278 +++--------------------------- src/meta/meta_base_wrapper.hpp | 2 +- src/utilities.hpp | 8 + types/groups/groupinfo.d.ts | 5 - types/groups/groupkeys.d.ts | 1 + types/shared.d.ts | 6 + 7 files changed, 303 insertions(+), 264 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 45acfef..a16d322 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -4,6 +4,8 @@ #include +#include "oxenc/bt_producer.h" + namespace session::nodeapi { MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : @@ -56,6 +58,8 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { }); } +/* #region SHARED ACTIONS */ + Napi::Value MetaGroupWrapper::needsPush(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { @@ -64,6 +68,77 @@ Napi::Value MetaGroupWrapper::needsPush(const Napi::CallbackInfo& info) { }); } +Napi::Value MetaGroupWrapper::push(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + auto to_push = Napi::Object::New(env); + + if (this->meta_group->members->needs_push()) + to_push["groupMember"s] = push_result_to_JS( + env, + this->meta_group->members->push(), + this->meta_group->members->storage_namespace()); + else + to_push["groupMember"s] = env.Null(); + + if (this->meta_group->info->needs_push()) + to_push["groupInfo"s] = push_result_to_JS( + env, + this->meta_group->info->push(), + this->meta_group->info->storage_namespace()); + else + to_push["groupInfo"s] = env.Null(); + + if (auto pending_config = this->meta_group->keys->pending_config()) + to_push["groupKeys"s] = push_key_entry_to_JS( + env, *(pending_config), this->meta_group->keys->storage_namespace()); + else + to_push["groupKeys"s] = env.Null(); + + return to_push; + }); +} + +Napi::Value MetaGroupWrapper::needsDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + return this->meta_group->members->needs_dump() || this->meta_group->info->needs_dump() || + this->meta_group->keys->needs_dump(); + }); +} + +Napi::Value MetaGroupWrapper::metaDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + + oxenc::bt_dict_producer combined; + + // NOTE: the keys have to be in ascii-sorted order: + combined.append("info", session::from_unsigned_sv(this->meta_group->info->dump())); + combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->dump())); + combined.append("members", session::from_unsigned_sv(this->meta_group->members->dump())); + auto to_dump = std::move(combined).str(); + + return ustring{to_unsigned_sv(to_dump)}; + }); +} + +Napi::Value MetaGroupWrapper::metaMakeDump(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + + oxenc::bt_dict_producer combined; + + // NOTE: the keys have to be in ascii-sorted order: + combined.append("info", session::from_unsigned_sv(this->meta_group->info->make_dump())); + combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->make_dump())); + combined.append( + "members", session::from_unsigned_sv(this->meta_group->members->make_dump())); + auto to_dump = std::move(combined).str(); + + return ustring{to_unsigned_sv(to_dump)}; + }); +} + void MetaGroupWrapper::metaConfirmPushed(const Napi::CallbackInfo& info) { wrapExceptions(info, [&]() { assertInfoLength(info, 1); @@ -209,6 +284,10 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { }); } +/* #endregion */ + +/* #region INFO ACTIONS */ + Napi::Value MetaGroupWrapper::infoGet(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { auto env = info.Env(); @@ -268,4 +347,192 @@ Napi::Value MetaGroupWrapper::infoSet(const Napi::CallbackInfo& info) { }); } +Napi::Value MetaGroupWrapper::infoDestroy(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + meta_group->info->destroy_group(); + return this->infoGet(info); + }); +} + +/* #endregion */ + +/* #region MEMBERS ACTIONS */ + +Napi::Value MetaGroupWrapper::memberGetAll(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + std::vector allMembers; + for (auto& member : *this->meta_group->members) { + allMembers.push_back(member); + } + return allMembers; + }); +} + +Napi::Value MetaGroupWrapper::memberGet(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + return meta_group->members->get(pubkeyHex); + }); +} + +Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto env = info.Env(); + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + return meta_group->members->get_or_construct(pubkeyHex); + }); +} + +Napi::Value MetaGroupWrapper::memberSetName(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsString(info[1]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto newName = toCppString(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.set_name(newName); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + +Napi::Value MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsBoolean(info[1]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.set_invited(failed); + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + +Napi::Value MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.set_accepted(); + + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + +Napi::Value MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertIsString(info[0]); + assertIsBoolean(info[1]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.set_promoted(failed); + + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + +Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsString(info[0]); + assertIsObject(info[1]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto profilePicture = profile_pic_from_object(info[1]); + + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.profile_picture = profilePicture; + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + +Napi::Value MetaGroupWrapper::memberErase(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + std::optional result; + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto erased = this->meta_group->members->erase(pubkeyHex); + if (erased) { + meta_group->keys->rekey(*(this->meta_group->info), *(this->meta_group->members)); + } + + return erased; + }); +} + +/* #endregion */ + +/* #region KEYS ACTIONS */ +Napi::Value MetaGroupWrapper::keysNeedsRekey(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys->needs_rekey(); }); +} + +Napi::Value MetaGroupWrapper::keyRekey(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + return meta_group->keys->rekey(*(meta_group->info), *(meta_group->members)); + }); +} + +// TODO key_supplement, swarm_make_subaccount, ... + +Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 3); + assertIsString(info[0]); + assertIsUInt8Array(info[1]); + assertIsNumber(info[2]); + + auto hash = toCppString(info[0], __PRETTY_FUNCTION__); + auto data = toCppBuffer(info[1], __PRETTY_FUNCTION__); + auto timestamp_ms = toCppInteger(info[2], __PRETTY_FUNCTION__); + + return meta_group->keys->load_key_message( + hash, data, timestamp_ms, *(this->meta_group->info), *(this->meta_group->members)); + }); +} + +Napi::Value MetaGroupWrapper::currentHashes(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); +} + +Napi::Value MetaGroupWrapper::encryptMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + + auto plaintext = toCppBuffer(info[0], __PRETTY_FUNCTION__); + return this->meta_group->keys->encrypt_message(plaintext); + }); +} +Napi::Value MetaGroupWrapper::decryptMessage(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsUInt8Array(info[0]); + + auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto decrypted = this->meta_group->keys->decrypt_message(ciphertext); + + return decrypt_result_to_JS(info.Env(), decrypted); + }); +} +/* #endregion */ + } // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index afc1e7e..be060db 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -41,277 +41,39 @@ class MetaGroupWrapper : public Napi::ObjectWrap { std::unique_ptr meta_group; /* Shared Actions */ - Napi::Value needsPush(const Napi::CallbackInfo& info); - - Napi::Value push(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - auto to_push = Napi::Object::New(env); - - if (this->meta_group->members->needs_push()) - to_push["groupMember"s] = push_result_to_JS( - env, - this->meta_group->members->push(), - this->meta_group->members->storage_namespace()); - else - to_push["groupMember"s] = env.Null(); - - if (this->meta_group->info->needs_push()) - to_push["groupInfo"s] = push_result_to_JS( - env, - this->meta_group->info->push(), - this->meta_group->info->storage_namespace()); - else - to_push["groupInfo"s] = env.Null(); - - if (auto pending_config = this->meta_group->keys->pending_config()) - to_push["groupKeys"s] = push_key_entry_to_JS( - env, *(pending_config), this->meta_group->keys->storage_namespace()); - else - to_push["groupKeys"s] = env.Null(); - - return to_push; - }); - } - - Napi::Value needsDump(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - return this->meta_group->members->needs_dump() || - this->meta_group->info->needs_dump() || this->meta_group->keys->needs_dump(); - }); - } - - Napi::Value metaDump(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - - oxenc::bt_dict_producer combined; - - // NB: the keys have to be in ascii-sorted order: - combined.append("info", session::from_unsigned_sv(this->meta_group->info->dump())); - combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->dump())); - combined.append( - "members", session::from_unsigned_sv(this->meta_group->members->dump())); - auto to_dump = std::move(combined).str(); - - return ustring{to_unsigned_sv(to_dump)}; - }); - } - - Napi::Value metaMakeDump(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - - oxenc::bt_dict_producer combined; - - // NB: the keys have to be in ascii-sorted order: - combined.append("info", session::from_unsigned_sv(this->meta_group->info->make_dump())); - combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->make_dump())); - combined.append( - "members", session::from_unsigned_sv(this->meta_group->members->make_dump())); - auto to_dump = std::move(combined).str(); - - return ustring{to_unsigned_sv(to_dump)}; - }); - } - + Napi::Value push(const Napi::CallbackInfo& info); + Napi::Value needsDump(const Napi::CallbackInfo& info); + Napi::Value metaDump(const Napi::CallbackInfo& info); + Napi::Value metaMakeDump(const Napi::CallbackInfo& info); void metaConfirmPushed(const Napi::CallbackInfo& info); Napi::Value metaMerge(const Napi::CallbackInfo& info); /** Info Actions */ - Napi::Value infoGet(const Napi::CallbackInfo& info); - Napi::Value infoSet(const Napi::CallbackInfo& info); - - Napi::Value infoDestroy(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - meta_group->info->destroy_group(); - return this->infoGet(info); - }); - } + Napi::Value infoDestroy(const Napi::CallbackInfo& info); /** Members Actions */ - - Napi::Value memberGetAll(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - std::vector allMembers; - for (auto& member : *this->meta_group->members) { - allMembers.push_back(member); - } - return allMembers; - }); - } - - Napi::Value memberGet(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - return meta_group->members->get(pubkeyHex); - }); - } - - Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - auto env = info.Env(); - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - return meta_group->members->get_or_construct(pubkeyHex); - }); - } - - Napi::Value memberSetName(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertIsString(info[0]); - assertIsString(info[1]); - - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto newName = toCppString(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_name(newName); - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); - }); - } - - Napi::Value memberSetInvited(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertIsString(info[0]); - assertIsBoolean(info[1]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_invited(failed); - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); - }); - } - - Napi::Value memberSetAccepted(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - assertIsString(info[0]); - - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_accepted(); - - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); - }); - } - - Napi::Value memberSetPromoted(const Napi::CallbackInfo& info) { - - return wrapResult(info, [&] { - assertIsString(info[0]); - assertIsBoolean(info[1]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_promoted(failed); - - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); - }); - } - - Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info) { - - return wrapResult(info, [&] { - assertInfoLength(info, 2); - assertIsString(info[0]); - assertIsObject(info[1]); - - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto profilePicture = profile_pic_from_object(info[1]); - - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.profile_picture = profilePicture; - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); - }); - } - - Napi::Value memberErase(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - assertIsString(info[0]); - - std::optional result; - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto erased = this->meta_group->members->erase(pubkeyHex); - if (erased) { - meta_group->keys->rekey(*(this->meta_group->info), *(this->meta_group->members)); - } - - return erased; - }); - } + Napi::Value memberGetAll(const Napi::CallbackInfo& info); + Napi::Value memberGet(const Napi::CallbackInfo& info); + Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); + Napi::Value memberSetName(const Napi::CallbackInfo& info); + Napi::Value memberSetInvited(const Napi::CallbackInfo& info); + Napi::Value memberSetAccepted(const Napi::CallbackInfo& info); + Napi::Value memberSetPromoted(const Napi::CallbackInfo& info); + Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info); + Napi::Value memberErase(const Napi::CallbackInfo& info); /** Keys Actions */ - - Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->keys->needs_rekey(); }); - } - - Napi::Value keyRekey(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - return meta_group->keys->rekey(*(meta_group->info), *(meta_group->members)); - }); - } - // TODO key_supplement, swarm_make_subaccount, ... - Napi::Value loadKeyMessage(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 3); - assertIsString(info[0]); - assertIsUInt8Array(info[1]); - assertIsNumber(info[2]); - - auto hash = toCppString(info[0], __PRETTY_FUNCTION__); - auto data = toCppBuffer(info[1], __PRETTY_FUNCTION__); - auto timestamp_ms = toCppInteger(info[2], __PRETTY_FUNCTION__); - - return meta_group->keys->load_key_message( - hash, - data, - timestamp_ms, - *(this->meta_group->info), - *(this->meta_group->members)); - }); - } - - Napi::Value currentHashes(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); - } - - Napi::Value encryptMessage(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - - auto plaintext = toCppBuffer(info[0], __PRETTY_FUNCTION__); - return this->meta_group->keys->encrypt_message(plaintext); - }); - } - Napi::Value decryptMessage(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { - assertInfoLength(info, 1); - assertIsUInt8Array(info[0]); - - auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); - auto decrypted = this->meta_group->keys->decrypt_message(ciphertext); - - return decrypt_result_to_JS(info.Env(), decrypted); - }); - } + Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info); + Napi::Value keyRekey(const Napi::CallbackInfo& info); + Napi::Value loadKeyMessage(const Napi::CallbackInfo& info); + Napi::Value currentHashes(const Napi::CallbackInfo& info); + Napi::Value encryptMessage(const Napi::CallbackInfo& info); + Napi::Value decryptMessage(const Napi::CallbackInfo& info); }; } // namespace session::nodeapi diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index a18bea6..eda8e47 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -86,7 +86,7 @@ class MetaBaseWrapper { } // Note, we keep shared_ptr for those as the Keys one need a reference to Members and - // Info on his own currently. + // Info on its own currently. auto info = std::make_shared( group_ed25519_pubkey, group_ed25519_secretkey, dumped_info); diff --git a/src/utilities.hpp b/src/utilities.hpp index ea0240e..2de8bb3 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -97,6 +97,7 @@ template <> struct toJs_impl { auto operator()(const Napi::Env& env, bool b) const { return Napi::Boolean::New(env, b); } }; + template <> struct toJs_impl { auto operator()(const Napi::Env& env, session::config::Namespace b) const { @@ -108,22 +109,26 @@ template struct toJs_impl>> { auto operator()(const Napi::Env& env, T n) const { return Napi::Number::New(env, n); } }; + template struct toJs_impl>> { auto operator()(const Napi::Env& env, std::string_view s) const { return Napi::String::New(env, s.data(), s.size()); } }; + template struct toJs_impl>> { auto operator()(const Napi::Env& env, ustring_view b) const { return Napi::Buffer::Copy(env, b.data(), b.size()); } }; + template struct toJs_impl>> { auto operator()(const Napi::Env& env, const T& val) { return val; } }; + template struct toJs_impl> { auto operator()(const Napi::Env& env, const std::vector& val) { @@ -133,6 +138,7 @@ struct toJs_impl> { return arr; } }; + template struct toJs_impl> { auto operator()(const Napi::Env& env, const std::unordered_set& set) { @@ -141,9 +147,11 @@ struct toJs_impl> { auto arr = Napi::Array::New(env, as_array.size()); for (size_t i = 0; i < as_array.size(); i++) arr[i] = toJs(env, as_array[i]); + return arr; } }; + template struct toJs_impl> { Napi::Value operator()(const Napi::Env& env, const std::optional& val) { diff --git a/types/groups/groupinfo.d.ts b/types/groups/groupinfo.d.ts index 052e3c2..bf9cb95 100644 --- a/types/groups/groupinfo.d.ts +++ b/types/groups/groupinfo.d.ts @@ -1,11 +1,6 @@ /// declare module 'libsession_util_nodejs' { - /** - * - * Group Wrapper Logics - */ - export type GroupInfoWrapper = { // GroupInfo related methods infoGet: () => GroupInfoGet; diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index d047152..23a4b60 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -2,6 +2,7 @@ declare module 'libsession_util_nodejs' { export type GroupKeysWrapper = { + // GroupKeys related methods keysNeedsRekey: () => boolean; keyRekey: () => Uint8Array; loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; diff --git a/types/shared.d.ts b/types/shared.d.ts index b0aae80..2e503d5 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -1,4 +1,7 @@ declare module 'libsession_util_nodejs' { + /** + * NOTE: For linting performance reasons, this type should only be used with small fixed size arrays (less < 100 items) + */ type FixedSizeArray = N extends N ? number extends N ? T[] @@ -14,6 +17,9 @@ declare module 'libsession_util_nodejs' { ? U : never; type Uint8ArrayWithoutIndex = Pick>; + /** + * NOTE: For linting performance reasons, this type should only be used with small fixed size arrays (less < 100 items) + */ type FixedSizeUint8Array = FixedSizeArray & Uint8ArrayWithoutIndex; /** From 5fe572feea7d7df2155eb61b62c9ed228b8bdeef Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 19 Oct 2023 16:14:59 +1100 Subject: [PATCH 24/64] chore: remove the fixedlength uint8array as it is not convenient at all we will need a better way to do this, but also have nice wrapping/unwrapping in the nodejs wrapper --- types/groups/metagroup.d.ts | 6 +++--- types/shared.d.ts | 28 +++++----------------------- types/user/userconfig.d.ts | 4 ++-- types/user/usergroups.d.ts | 2 +- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index d23aefc..df88100 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -7,9 +7,9 @@ declare module 'libsession_util_nodejs' { export type ConfirmKeysPush = [data: Uint8Array, hash: string, timestampMs: number]; export type GroupWrapperConstructor = { - userEd25519Secretkey: FixedSizeUint8Array<64>; - groupEd25519Pubkey: FixedSizeUint8Array<32>; // the ed25519 pubkey without the 03 prefix - groupEd25519Secretkey: FixedSizeUint8Array<64> | null; // the ed25519 privkey if we have it (comes from usergroup wrapper if we have it) + userEd25519Secretkey: Uint8Array; // (len 64) + groupEd25519Pubkey: Uint8Array; // the ed25519 pubkey without the 03 prefix (len 32) + groupEd25519Secretkey: Uint8Array | null; // the ed25519 privkey if we have it (len 64) (comes from usergroup wrapper if we have it) metaDumped: Uint8Array | null; }; diff --git a/types/shared.d.ts b/types/shared.d.ts index 2e503d5..d61bc8d 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -1,26 +1,8 @@ declare module 'libsession_util_nodejs' { - /** - * NOTE: For linting performance reasons, this type should only be used with small fixed size arrays (less < 100 items) - */ - type FixedSizeArray = N extends N - ? number extends N - ? T[] - : _FixedSizeArray - : never; - type _FixedSizeArray = R['length'] extends N - ? R - : _FixedSizeArray; - - type KnownKeys = { - [K in keyof T]: string extends K ? never : number extends K ? never : K; - } extends { [_ in keyof T]: infer U } - ? U - : never; - type Uint8ArrayWithoutIndex = Pick>; - /** - * NOTE: For linting performance reasons, this type should only be used with small fixed size arrays (less < 100 items) - */ - type FixedSizeUint8Array = FixedSizeArray & Uint8ArrayWithoutIndex; + type Uint8ArrayFixedLength = { + buffer: Uint8Array; + length: T; + }; /** * Allow a single type to be Nullable. i.e. string => string | null @@ -151,7 +133,7 @@ declare module 'libsession_util_nodejs' { export type GroupInfoGet = GroupInfoShared & { isDestroyed: boolean; - secretKey?: FixedSizeUint8Array<64>; + secretKey?: Uint8Array; // len 64 }; export type GroupInfoSet = GroupInfoShared & {}; diff --git a/types/user/userconfig.d.ts b/types/user/userconfig.d.ts index 54d65b1..5e025c7 100644 --- a/types/user/userconfig.d.ts +++ b/types/user/userconfig.d.ts @@ -13,13 +13,13 @@ declare module 'libsession_util_nodejs' { name: string; priority: number; url: string; - key: Uint8Array; // FixedSizeUint8Array<32> + key: Uint8Array; // TODO could be made a FixedLength<32> but that impacts a bunch of things // expirySeconds: number | null; // <= 0 is returned as null }; setUserInfo: ( name: string, priority: number, - profilePic: { url: string; key: Uint8Array } | null // FixedSizeUint8Array<32> + profilePic: { url: string; key: Uint8Array } | null // TODO could be made a FixedLength<32> but that impacts a bunch of things // expirySeconds: number, ) => void; setEnableBlindedMsgRequest: (msgRequest: boolean) => void; diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 8989ef2..5fd202e 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -40,7 +40,7 @@ declare module 'libsession_util_nodejs' { type UserGroupsGet = BaseUserGroup & { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. - secretKey: FixedSizeUint8Array<64> | null; + secretKey: Uint8Array | null; // len 64 authData: Uint8Array | null; name: string | null; }; From b337a9586d45dfb7481bf996bada053d10799787 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 27 Oct 2023 14:53:56 +1100 Subject: [PATCH 25/64] chore: bump to 0.4.0 for groups --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bd484cb..5ed56ec 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "main": "index.js", "name": "libsession_util_nodejs", "description": "Wrappers for the Session Util Library", - "version": "0.2.6", + "version": "0.4.0", "license": "GPL-3.0", "author": { "name": "Oxen Project", From 373edca7f62e987b21d44fcbca734638a6a7fb9a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 27 Oct 2023 15:54:16 +1100 Subject: [PATCH 26/64] chore: ignore files in archive for release --- .gitattributes | 5 ++++- CMakeLists.txt | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 6ba9b93..1a63ea1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,7 @@ libsession-util/external/libsodium-internal/test export-ignore libsession-util/external/zstd/doc export-ignore libsession-util/tests export-ignore -libsession-util/external/oxen-encoding/tests export-ignore \ No newline at end of file +libsession-util/external/oxen-encoding/tests export-ignore +libsession-util/external/zstd/tests export-ignore +libsession-util/external/nlohmann-json/tests export-ignore +libsession-util/external/nlohmann-json/docs export-ignore diff --git a/CMakeLists.txt b/CMakeLists.txt index 22960c6..d665778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +# when building from a release of libsession on desktop, it complains that ios-cmake is not up to date +# as it is not part of the archive. We actually don't care about it on session-desktop +set(SUBMODULE_CHECK OFF) + file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp) add_subdirectory(libsession-util) From 13cb613d868a334fec70b413e77ba3cc47766683 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 27 Oct 2023 14:41:41 +1100 Subject: [PATCH 27/64] feat: add subaccount calls --- libsession-util | 2 +- src/groups/meta_group_wrapper.cpp | 37 ++++++++++++++++++++++++++++--- src/groups/meta_group_wrapper.hpp | 15 ++++++++++++- src/user_groups_config.cpp | 1 + src/utilities.cpp | 5 ----- src/utilities.hpp | 8 +++---- types/groups/groupkeys.d.ts | 5 +++++ types/groups/groupmembers.d.ts | 21 ++++++++++-------- types/groups/metagroup.d.ts | 6 ++++- types/shared.d.ts | 13 ++++++++++- types/user/usergroups.d.ts | 6 ++--- 11 files changed, 91 insertions(+), 28 deletions(-) diff --git a/libsession-util b/libsession-util index 6c4e38c..986caaa 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 6c4e38c4ed7f3a153428491bda588c782f8e0c60 +Subproject commit 986caaa28305fa6481238d98e6f7dd096c562336 diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index a16d322..ff4c9d1 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -5,6 +5,7 @@ #include #include "oxenc/bt_producer.h" +#include "session/types.hpp" namespace session::nodeapi { @@ -55,6 +56,8 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), + InstanceMethod("makeSwarmSubAccount", &MetaGroupWrapper::makeSwarmSubAccount), + InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), }); } @@ -118,7 +121,7 @@ Napi::Value MetaGroupWrapper::metaDump(const Napi::CallbackInfo& info) { combined.append("members", session::from_unsigned_sv(this->meta_group->members->dump())); auto to_dump = std::move(combined).str(); - return ustring{to_unsigned_sv(to_dump)}; + return session::ustring{to_unsigned_sv(to_dump)}; }); } @@ -492,8 +495,6 @@ Napi::Value MetaGroupWrapper::keyRekey(const Napi::CallbackInfo& info) { }); } -// TODO key_supplement, swarm_make_subaccount, ... - Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 3); @@ -522,6 +523,7 @@ Napi::Value MetaGroupWrapper::encryptMessage(const Napi::CallbackInfo& info) { return this->meta_group->keys->encrypt_message(plaintext); }); } + Napi::Value MetaGroupWrapper::decryptMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); @@ -533,6 +535,35 @@ Napi::Value MetaGroupWrapper::decryptMessage(const Napi::CallbackInfo& info) { return decrypt_result_to_JS(info.Env(), decrypted); }); } + +Napi::Value MetaGroupWrapper::makeSwarmSubAccount(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto memberPk = toCppString(info[0], __PRETTY_FUNCTION__); + ustring subaccount = this->meta_group->keys->swarm_make_subaccount(memberPk); + + session::nodeapi::checkOrThrow( + subaccount.length() == 100, "expected subaccount to be 100 bytes long"); + + return subaccount; + }); +} + +Napi::Value MetaGroupWrapper::swarmSubaccountSign(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + assertIsUInt8Array(info[0]); + assertIsUInt8Array(info[1]); + + auto message = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto authdata = toCppBuffer(info[1], __PRETTY_FUNCTION__); + auto subaccountSign = this->meta_group->keys->swarm_subaccount_sign(message, authdata); + + return subaccountSign; + }); +} /* #endregion */ } // namespace session::nodeapi diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index be060db..b57887e 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -31,6 +31,18 @@ struct toJs_impl { } }; +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const Keys::swarm_auth& auth) { + auto obj = Napi::Object::New(env); + + obj["subaccount"] = toJs(env, auth.subaccount); + obj["subaccount_sig"] = toJs(env, auth.subaccount_sig); + obj["signature"] = toJs(env, auth.signature); + return obj; + } +}; + class MetaGroupWrapper : public Napi::ObjectWrap { public: static void Init(Napi::Env env, Napi::Object exports); @@ -66,7 +78,6 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberErase(const Napi::CallbackInfo& info); /** Keys Actions */ - // TODO key_supplement, swarm_make_subaccount, ... Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info); Napi::Value keyRekey(const Napi::CallbackInfo& info); @@ -74,6 +85,8 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value currentHashes(const Napi::CallbackInfo& info); Napi::Value encryptMessage(const Napi::CallbackInfo& info); Napi::Value decryptMessage(const Napi::CallbackInfo& info); + Napi::Value makeSwarmSubAccount(const Napi::CallbackInfo& info); + Napi::Value swarmSubaccountSign(const Napi::CallbackInfo& info); }; } // namespace session::nodeapi diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 39ce40c..01124c7 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -67,6 +67,7 @@ struct toJs_impl { obj["priority"] = toJs(env, info.priority); obj["joinedAtSeconds"] = toJs(env, info.joined_at); obj["name"] = toJs(env, info.name); + obj["authData"] = toJs(env, info.auth_data); // TODO kicked and setKicked todo return obj; diff --git a/src/utilities.cpp b/src/utilities.cpp index 8245b88..a6341b5 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -6,11 +6,6 @@ namespace session::nodeapi { -static void checkOrThrow(bool condition, const char* msg) { - if (!condition) - throw std::invalid_argument{msg}; -} - void assertInfoLength(const Napi::CallbackInfo& info, const int expected) { checkOrThrow(info.Length() == expected, "Invalid number of arguments"); } diff --git a/src/utilities.hpp b/src/utilities.hpp index 2de8bb3..a8bd5eb 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -16,10 +16,10 @@ namespace session::nodeapi { using namespace std::literals; -// template -// T object_wrap_impl(const Napi::ObjectWrap&); -// template -// using object_wrap_t = decltype(object_wrap_impl(std::declval())); +static void checkOrThrow(bool condition, const char* msg) { + if (!condition) + throw std::invalid_argument{msg}; +} void assertInfoLength(const Napi::CallbackInfo& info, const int expected); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 23a4b60..12d3744 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -10,5 +10,10 @@ declare module 'libsession_util_nodejs' { currentHashes: () => Array; encryptMessage: (plaintext: Uint8Array) => Uint8Array; decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; + makeSwarmSubAccount: (memberPubkeyHex: PubkeyType) => Uint8ArrayLen100; + swarmSubaccountSign: ( + message: Uint8Array, + authData: Uint8ArrayLen100 + ) => SwarmSubAccountSignResult; }; } diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 68ca217..432e9e0 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -7,7 +7,7 @@ declare module 'libsession_util_nodejs' { * */ type GroupMemberShared = { - pubkeyHex: string; + pubkeyHex: PubkeyType; name: string | null; profilePicture: ProfilePicture | null; }; @@ -22,18 +22,21 @@ declare module 'libsession_util_nodejs' { type GroupMemberWrapper = { // GroupMember related methods - memberGet: (pubkeyHex: string) => GroupMemberGet | null; - memberGetOrConstruct: (pubkeyHex: string) => GroupMemberGet; + memberGet: (pubkeyHex: PubkeyType) => GroupMemberGet | null; + memberGetOrConstruct: (pubkeyHex: PubkeyType) => GroupMemberGet; memberGetAll: () => Array; // setters - memberSetName: (pubkeyHex: string, newName: string) => GroupMemberGet; - memberSetInvited: (pubkeyHex: string, failed: boolean) => GroupMemberGet; - memberSetPromoted: (pubkeyHex: string, failed: boolean) => GroupMemberGet; - memberSetAccepted: (pubkeyHex: string) => GroupMemberGet; - memberSetProfilePicture: (pubkeyHex: string, profilePicture: ProfilePicture) => GroupMemberGet; + memberSetName: (pubkeyHex: PubkeyType, newName: string) => GroupMemberGet; + memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; + memberSetPromoted: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; + memberSetAccepted: (pubkeyHex: PubkeyType) => GroupMemberGet; + memberSetProfilePicture: ( + pubkeyHex: PubkeyType, + profilePicture: ProfilePicture + ) => GroupMemberGet; // eraser - memberErase: (pubkeyHex: string) => null; + memberErase: (pubkeyHex: PubkeyType) => null; }; } diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index df88100..2a02b03 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -90,6 +90,8 @@ declare module 'libsession_util_nodejs' { public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; public encryptMessage: MetaGroupWrapper['encryptMessage']; public decryptMessage: MetaGroupWrapper['decryptMessage']; + public makeSwarmSubAccount: MetaGroupWrapper['makeSwarmSubAccount']; + public swarmSubaccountSign: MetaGroupWrapper['swarmSubaccountSign']; } export type MetaGroupActionsType = @@ -125,5 +127,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall + | MakeActionCall; } diff --git a/types/shared.d.ts b/types/shared.d.ts index d61bc8d..428c727 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -133,8 +133,19 @@ declare module 'libsession_util_nodejs' { export type GroupInfoGet = GroupInfoShared & { isDestroyed: boolean; - secretKey?: Uint8Array; // len 64 + secretKey?: Uint8ArrayLen64; // len 64 }; export type GroupInfoSet = GroupInfoShared & {}; + + export type SwarmSubAccountSignResult = { + subaccount: string; + subaccount_sig: string; // keeping the case like this so we can send it as is (this is what the snode API expects) + signature: string; + }; + + // those types are not enforced currently, they all are just Uint8Arrays, but having them separate right away will make the enforcing of them later, easier + export type Uint8ArrayLen64 = Uint8Array; + export type Uint8ArrayLen32 = Uint8Array; + export type Uint8ArrayLen100 = Uint8Array; } diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 5fd202e..f9c9bfd 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -32,7 +32,7 @@ declare module 'libsession_util_nodejs' { export type LegacyGroupInfo = BaseUserGroup & { pubkeyHex: string; // The legacy group "session id" (33 bytes). name: string; // human-readable; this should normally always be set, but in theory could be set to an empty string. - encPubkey: Uint8Array; // bytes (32 or empty) + encPubkey: Uint8ArrayLen32; // bytes (32 or empty) encSeckey: Uint8Array; // bytes (32 or empty) // disappearingTimerSeconds: number; // in seconds, 0 == disabled. members: Array; @@ -40,8 +40,8 @@ declare module 'libsession_util_nodejs' { type UserGroupsGet = BaseUserGroup & { pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. - secretKey: Uint8Array | null; // len 64 - authData: Uint8Array | null; + secretKey: Uint8ArrayLen64 | null; // len 64 + authData: Uint8ArrayLen100 | null; // len 100 name: string | null; }; From 0ad80e52d88480cb6ee0d48a94be38734ea8d5a7 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 2 Nov 2023 12:57:18 +1100 Subject: [PATCH 28/64] feat: add subaccount verify and subaccount token --- src/groups/meta_group_wrapper.cpp | 67 ++++++++++++++++++++++++++++--- src/groups/meta_group_wrapper.hpp | 3 ++ types/groups/groupkeys.d.ts | 4 ++ types/groups/groupmembers.d.ts | 2 +- types/groups/metagroup.d.ts | 5 ++- types/shared.d.ts | 6 ++- types/user/contacts.d.ts | 2 +- types/user/usergroups.d.ts | 4 +- 8 files changed, 80 insertions(+), 13 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index ff4c9d1..8e22a50 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -57,6 +57,9 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), InstanceMethod("makeSwarmSubAccount", &MetaGroupWrapper::makeSwarmSubAccount), + InstanceMethod("swarmSubAccountToken", &MetaGroupWrapper::swarmSubAccountToken), + InstanceMethod( + "swarmVerifySubAccount", &MetaGroupWrapper::swarmVerifySubAccount), InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), }); } @@ -469,16 +472,22 @@ Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& Napi::Value MetaGroupWrapper::memberErase(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsString(info[0]); + auto toRemoveJSValue = info[0]; - std::optional result; - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto erased = this->meta_group->members->erase(pubkeyHex); - if (erased) { + assertIsArray(toRemoveJSValue); + + auto toRemoveJS = toRemoveJSValue.As(); + auto rekeyed = false; + for (uint32_t i = 0; i < toRemoveJS.Length(); i++) { + auto pubkeyHex = toCppString(toRemoveJS[i], __PRETTY_FUNCTION__); + rekeyed |= this->meta_group->members->erase(pubkeyHex); + } + + if (rekeyed) { meta_group->keys->rekey(*(this->meta_group->info), *(this->meta_group->members)); } - return erased; + return rekeyed; }); } @@ -551,6 +560,52 @@ Napi::Value MetaGroupWrapper::makeSwarmSubAccount(const Napi::CallbackInfo& info }); } +Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto memberPk = toCppString(info[0], __PRETTY_FUNCTION__); + ustring subaccount = this->meta_group->keys->swarm_subaccount_token(memberPk); + + session::nodeapi::checkOrThrow( + subaccount.length() == 36, "expected subaccount tken to be 36 bytes long"); + + return subaccount; + }); +} + +Napi::Value MetaGroupWrapper::swarmVerifySubAccount(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsUInt8Array(info[0]); + + auto signingValue = toCppBuffer(info[0], __PRETTY_FUNCTION__); + return this->meta_group->keys->swarm_verify_subaccount(signingValue); + }); +} + +Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + auto membersJSValue = info[0]; + assertIsArray(membersJSValue); + + auto membersJS = membersJSValue.As(); + uint32_t arrayLength = membersJS.Length(); + std::vector membersToAdd; + membersToAdd.reserve(arrayLength); + std::vector keyMessages; + keyMessages.reserve(arrayLength); + + for (uint32_t i = 0; i < membersJS.Length(); i++) { + auto memberPk = toCppString(membersJS[i], __PRETTY_FUNCTION__); + keyMessages.push_back(this->meta_group->keys->key_supplement(memberPk)); + } + return keyMessages; + }); +} + Napi::Value MetaGroupWrapper::swarmSubaccountSign(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 2); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index b57887e..56b4d4b 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -86,7 +86,10 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value encryptMessage(const Napi::CallbackInfo& info); Napi::Value decryptMessage(const Napi::CallbackInfo& info); Napi::Value makeSwarmSubAccount(const Napi::CallbackInfo& info); + Napi::Value swarmSubAccountToken(const Napi::CallbackInfo& info); + Napi::Value generateSupplementKeys(const Napi::CallbackInfo& info); Napi::Value swarmSubaccountSign(const Napi::CallbackInfo& info); + Napi::Value swarmVerifySubAccount(const Napi::CallbackInfo& info); }; } // namespace session::nodeapi diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 12d3744..6039441 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -11,9 +11,13 @@ declare module 'libsession_util_nodejs' { encryptMessage: (plaintext: Uint8Array) => Uint8Array; decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; makeSwarmSubAccount: (memberPubkeyHex: PubkeyType) => Uint8ArrayLen100; + generateSupplementKeys: (membersPubkeyHex: Array) => Array; swarmSubaccountSign: ( message: Uint8Array, authData: Uint8ArrayLen100 ) => SwarmSubAccountSignResult; + + swarmSubAccountToken: (memberPk: PubkeyType) => Uint8ArrayLen36; + swarmVerifySubAccount: (signingValue: Uint8ArrayLen100) => boolean; }; } diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 432e9e0..9744995 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -37,6 +37,6 @@ declare module 'libsession_util_nodejs' { ) => GroupMemberGet; // eraser - memberErase: (pubkeyHex: PubkeyType) => null; + memberErase: (members: Array) => boolean; }; } diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 2a02b03..bf9d8de 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -129,5 +129,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall; } diff --git a/types/shared.d.ts b/types/shared.d.ts index 428c727..8a34614 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -120,7 +120,8 @@ declare module 'libsession_util_nodejs' { [Property in keyof Omit]: AsyncGroupWrapper; }; - export type PriorityType = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned + export type WithPriority = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned + export type WithGroupPubkey = { groupPk: GroupPubkeyType }; type GroupInfoShared = { name: string | null; @@ -147,5 +148,6 @@ declare module 'libsession_util_nodejs' { // those types are not enforced currently, they all are just Uint8Arrays, but having them separate right away will make the enforcing of them later, easier export type Uint8ArrayLen64 = Uint8Array; export type Uint8ArrayLen32 = Uint8Array; - export type Uint8ArrayLen100 = Uint8Array; + export type Uint8ArrayLen36 = Uint8Array; // subaccount tokens are 36 bytes long + export type Uint8ArrayLen100 = Uint8Array; // subaccount authdata are 100 bytes long } diff --git a/types/user/contacts.d.ts b/types/user/contacts.d.ts index 0db43cf..cb819b1 100644 --- a/types/user/contacts.d.ts +++ b/types/user/contacts.d.ts @@ -16,7 +16,7 @@ declare module 'libsession_util_nodejs' { export type ContactsWrapperActionsCalls = MakeWrapperActionCalls; - type ContactInfoShared = PriorityType & { + type ContactInfoShared = WithPriority & { id: string; name?: string; nickname?: string; diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index f9c9bfd..35c2cb8 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -16,7 +16,7 @@ declare module 'libsession_util_nodejs' { }; export type CommunityInfo = CommunityDetails & - PriorityType & { + WithPriority & { pubkeyHex: string; }; @@ -25,7 +25,7 @@ declare module 'libsession_util_nodejs' { isAdmin: boolean; }; - type BaseUserGroup = PriorityType & { + type BaseUserGroup = WithPriority & { joinedAtSeconds: number; // equivalent to the lastJoinedTimestamp in Session desktop but in seconds rather than MS }; From 9fcc2f05ff4f2002dfb6e21134ef2b81d7728614 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 13 Nov 2023 15:48:37 +1100 Subject: [PATCH 29/64] fix: memberErase takes a list and rekeys, add memberSetAdmin --- src/groups/meta_group_wrapper.cpp | 26 +++++++++++++++++++++++--- src/groups/meta_group_wrapper.hpp | 3 ++- types/groups/groupkeys.d.ts | 2 +- types/groups/groupmembers.d.ts | 3 ++- types/groups/metagroup.d.ts | 6 ++++-- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 8e22a50..3a48863 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -42,9 +42,10 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), InstanceMethod("memberSetAccepted", &MetaGroupWrapper::memberSetAccepted), InstanceMethod("memberSetPromoted", &MetaGroupWrapper::memberSetPromoted), + InstanceMethod("memberSetAdmin", &MetaGroupWrapper::memberSetAdmin), InstanceMethod( "memberSetProfilePicture", &MetaGroupWrapper::memberSetProfilePicture), - InstanceMethod("memberErase", &MetaGroupWrapper::memberErase), + InstanceMethod("memberEraseAndRekey", &MetaGroupWrapper::memberEraseAndRekey), // keys exposed functions @@ -61,6 +62,8 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod( "swarmVerifySubAccount", &MetaGroupWrapper::swarmVerifySubAccount), InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), + InstanceMethod( + "generateSupplementKeys", &MetaGroupWrapper::generateSupplementKeys), }); } @@ -440,6 +443,7 @@ Napi::Value MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) Napi::Value MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { + assertInfoLength(info, 2); assertIsString(info[0]); assertIsBoolean(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); @@ -452,6 +456,22 @@ Napi::Value MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) }); } +Napi::Value MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { + + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + // Note: this step might add an admin which was removed back once he accepts the promotion, + // but there is not much we can do about it + auto m = this->meta_group->members->get_or_construct(pubkeyHex); + m.admin = true; + + this->meta_group->members->set(m); + return this->meta_group->members->get_or_construct(m.session_id); + }); +} + Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { @@ -469,7 +489,7 @@ Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& }); } -Napi::Value MetaGroupWrapper::memberErase(const Napi::CallbackInfo& info) { +Napi::Value MetaGroupWrapper::memberEraseAndRekey(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); auto toRemoveJSValue = info[0]; @@ -571,7 +591,7 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf session::nodeapi::checkOrThrow( subaccount.length() == 36, "expected subaccount tken to be 36 bytes long"); - return subaccount; + return oxenc::to_hex(subaccount); }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 56b4d4b..de250b9 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -74,8 +74,9 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberSetInvited(const Napi::CallbackInfo& info); Napi::Value memberSetAccepted(const Napi::CallbackInfo& info); Napi::Value memberSetPromoted(const Napi::CallbackInfo& info); + Napi::Value memberSetAdmin(const Napi::CallbackInfo& info); Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info); - Napi::Value memberErase(const Napi::CallbackInfo& info); + Napi::Value memberEraseAndRekey(const Napi::CallbackInfo& info); /** Keys Actions */ diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 6039441..fae4cea 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -17,7 +17,7 @@ declare module 'libsession_util_nodejs' { authData: Uint8ArrayLen100 ) => SwarmSubAccountSignResult; - swarmSubAccountToken: (memberPk: PubkeyType) => Uint8ArrayLen36; + swarmSubAccountToken: (memberPk: PubkeyType) => string; // hex encoded swarmVerifySubAccount: (signingValue: Uint8ArrayLen100) => boolean; }; } diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 9744995..ff55ce6 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -30,6 +30,7 @@ declare module 'libsession_util_nodejs' { memberSetName: (pubkeyHex: PubkeyType, newName: string) => GroupMemberGet; memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; memberSetPromoted: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; + memberSetAdmin: (pubkeyHex: PubkeyType) => GroupMemberGet; memberSetAccepted: (pubkeyHex: PubkeyType) => GroupMemberGet; memberSetProfilePicture: ( pubkeyHex: PubkeyType, @@ -37,6 +38,6 @@ declare module 'libsession_util_nodejs' { ) => GroupMemberGet; // eraser - memberErase: (members: Array) => boolean; + memberEraseAndRekey: (members: Array) => boolean; }; } diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index bf9d8de..699f6df 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -79,8 +79,9 @@ declare module 'libsession_util_nodejs' { public memberSetAccepted: MetaGroupWrapper['memberSetAccepted']; public memberSetName: MetaGroupWrapper['memberSetName']; public memberSetPromoted: MetaGroupWrapper['memberSetPromoted']; + public memberSetAdmin: MetaGroupWrapper['memberSetAdmin']; public memberSetInvited: MetaGroupWrapper['memberSetInvited']; - public memberErase: MetaGroupWrapper['memberErase']; + public memberEraseAndRekey: MetaGroupWrapper['memberEraseAndRekey']; public memberSetProfilePicture: MetaGroupWrapper['memberSetProfilePicture']; // keys @@ -117,8 +118,9 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall | MakeActionCall // keys actions From 1a1f771e23a197c10cf9d27fbadfe001db99415b Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 13 Nov 2023 16:13:15 +1100 Subject: [PATCH 30/64] fix: add admin boolean on usergroupget --- src/groups/meta_group_wrapper.hpp | 1 + types/groups/groupmembers.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index de250b9..658a2d5 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -26,6 +26,7 @@ struct toJs_impl { obj["promotionPending"] = toJs(env, info.promotion_pending()); obj["promotionFailed"] = toJs(env, info.promotion_failed()); obj["promoted"] = toJs(env, info.promoted()); + obj["admin"] = toJs(env, info.admin); return obj; } diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index ff55ce6..9628b77 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -18,6 +18,7 @@ declare module 'libsession_util_nodejs' { promotionPending: boolean; promotionFailed: boolean; promoted: boolean; + admin: boolean; }; type GroupMemberWrapper = { From 322d3daedfc79476eb8df4345cfd60a9714fd982 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 16 Nov 2023 14:09:12 +1100 Subject: [PATCH 31/64] feat: add loadAdminKeys for handling incoming promote message --- libsession-util | 2 +- src/base_config.cpp | 2 +- src/base_config.hpp | 2 +- src/convo_info_volatile_config.cpp | 6 +++--- src/groups/meta_group_wrapper.cpp | 34 +++++++++++++++++++++--------- src/groups/meta_group_wrapper.hpp | 1 + src/meta/meta_base_wrapper.hpp | 4 ++-- src/profile_pic.cpp | 2 +- src/user_config.cpp | 2 +- src/user_groups_config.cpp | 2 +- src/utilities.cpp | 10 +++++---- src/utilities.hpp | 4 ++-- types/groups/groupkeys.d.ts | 1 + types/groups/metagroup.d.ts | 3 ++- 14 files changed, 47 insertions(+), 28 deletions(-) diff --git a/libsession-util b/libsession-util index 986caaa..20cdae8 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 986caaa28305fa6481238d98e6f7dd096c562336 +Subproject commit 20cdae81cb277d9d13d86765b8bd1e14f13d9643 diff --git a/src/base_config.cpp b/src/base_config.cpp index 45314fd..57163f8 100644 --- a/src/base_config.cpp +++ b/src/base_config.cpp @@ -46,7 +46,7 @@ Napi::Value ConfigBaseImpl::makeDump(const Napi::CallbackInfo& info) { void ConfigBaseImpl::confirmPushed(const Napi::CallbackInfo& info) { return wrapResult(info, [&]() { assertInfoLength(info, 2); - assertIsNumber(info[0]); + assertIsNumber(info[0], "confirmPushed"); assertIsString(info[1]); get_config().confirm_pushed( diff --git a/src/base_config.hpp b/src/base_config.hpp index 9f41718..c84f528 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -92,7 +92,7 @@ class ConfigBaseImpl { assertInfoLength(info, 2); // we should get secret key as first arg and optional dumped as second argument - assertIsUInt8Array(info[0]); + assertIsUInt8Array(info[0], "base construct"); assertIsUInt8ArrayOrNull(info[1]); ustring_view secretKey = toCppBufferView(info[0], class_name + ".new"); diff --git a/src/convo_info_volatile_config.cpp b/src/convo_info_volatile_config.cpp index ddf3991..b494791 100644 --- a/src/convo_info_volatile_config.cpp +++ b/src/convo_info_volatile_config.cpp @@ -107,7 +107,7 @@ void ConvoInfoVolatileWrapper::set1o1(const Napi::CallbackInfo& info) { assertIsString(first); auto second = info[1]; - assertIsNumber(second); + assertIsNumber(second, "set1o1"); auto third = info[2]; assertIsBoolean(third); @@ -144,7 +144,7 @@ void ConvoInfoVolatileWrapper::setLegacyGroup(const Napi::CallbackInfo& info) { auto first = info[0]; assertIsString(first); auto second = info[1]; - assertIsNumber(second); + assertIsNumber(second, "setLegacyGroup"); auto third = info[2]; assertIsBoolean(third); @@ -194,7 +194,7 @@ void ConvoInfoVolatileWrapper::setCommunityByFullUrl(const Napi::CallbackInfo& i assertIsString(first); auto second = info[1]; - assertIsNumber(second); + assertIsNumber(second, "setCommunityByFullUrl"); auto third = info[2]; assertIsBoolean(third); diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 3a48863..a662543 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -61,6 +61,8 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("swarmSubAccountToken", &MetaGroupWrapper::swarmSubAccountToken), InstanceMethod( "swarmVerifySubAccount", &MetaGroupWrapper::swarmVerifySubAccount), + InstanceMethod("loadAdminKeys", &MetaGroupWrapper::loadAdminKeys), + InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), InstanceMethod( "generateSupplementKeys", &MetaGroupWrapper::generateSupplementKeys), @@ -220,8 +222,8 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { Napi::Object itemObject = item.As(); assertIsString(itemObject.Get("hash")); - assertIsUInt8Array(itemObject.Get("data")); - assertIsNumber(itemObject.Get("timestampMs")); + assertIsUInt8Array(itemObject.Get("data"), "groupKeys merge"); + assertIsNumber(itemObject.Get("timestampMs"), "timestampMs groupKeys"); auto hash = toCppString(itemObject.Get("hash"), "meta.merge keys hash"); auto data = toCppBuffer(itemObject.Get("data"), "meta.merge keys data"); @@ -254,7 +256,7 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { Napi::Object itemObject = item.As(); assertIsString(itemObject.Get("hash")); - assertIsUInt8Array(itemObject.Get("data")); + assertIsUInt8Array(itemObject.Get("data"), "groupInfo merge"); conf_strs.emplace_back( toCppString(itemObject.Get("hash"), "meta.merge"), toCppBufferView(itemObject.Get("data"), "meta.merge")); @@ -279,7 +281,7 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { Napi::Object itemObject = item.As(); assertIsString(itemObject.Get("hash")); - assertIsUInt8Array(itemObject.Get("data")); + assertIsUInt8Array(itemObject.Get("data"), "groupMember merge"); conf_strs.emplace_back( toCppString(itemObject.Get("hash"), "meta.merge"), toCppBufferView(itemObject.Get("data"), "meta.merge")); @@ -528,8 +530,8 @@ Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 3); assertIsString(info[0]); - assertIsUInt8Array(info[1]); - assertIsNumber(info[2]); + assertIsUInt8Array(info[1], __PRETTY_FUNCTION__); + assertIsNumber(info[2], __PRETTY_FUNCTION__); auto hash = toCppString(info[0], __PRETTY_FUNCTION__); auto data = toCppBuffer(info[1], __PRETTY_FUNCTION__); @@ -556,7 +558,7 @@ Napi::Value MetaGroupWrapper::encryptMessage(const Napi::CallbackInfo& info) { Napi::Value MetaGroupWrapper::decryptMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsUInt8Array(info[0]); + assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); auto decrypted = this->meta_group->keys->decrypt_message(ciphertext); @@ -598,13 +600,25 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf Napi::Value MetaGroupWrapper::swarmVerifySubAccount(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsUInt8Array(info[0]); + assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); auto signingValue = toCppBuffer(info[0], __PRETTY_FUNCTION__); return this->meta_group->keys->swarm_verify_subaccount(signingValue); }); } +Napi::Value MetaGroupWrapper::loadAdminKeys(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); + + auto secret = toCppBuffer(info[0], __PRETTY_FUNCTION__); + this->meta_group->keys->load_admin_key( + secret, *(this->meta_group->info), *(this->meta_group->members)); + return info.Env().Null(); + }); +} + Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); @@ -629,8 +643,8 @@ Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& i Napi::Value MetaGroupWrapper::swarmSubaccountSign(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 2); - assertIsUInt8Array(info[0]); - assertIsUInt8Array(info[1]); + assertIsUInt8Array(info[0], "swarmSubaccountSign 0"); + assertIsUInt8Array(info[1], "swarmSubaccountSign 1"); auto message = toCppBuffer(info[0], __PRETTY_FUNCTION__); auto authdata = toCppBuffer(info[1], __PRETTY_FUNCTION__); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 658a2d5..33b370c 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -92,6 +92,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value generateSupplementKeys(const Napi::CallbackInfo& info); Napi::Value swarmSubaccountSign(const Napi::CallbackInfo& info); Napi::Value swarmVerifySubAccount(const Napi::CallbackInfo& info); + Napi::Value loadAdminKeys(const Napi::CallbackInfo& info); }; } // namespace session::nodeapi diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index eda8e47..73ee4ab 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -46,12 +46,12 @@ class MetaBaseWrapper { if (obj.IsEmpty()) throw std::invalid_argument("constructGroupWrapper received empty"); - assertIsUInt8Array(obj.Get("userEd25519Secretkey")); + assertIsUInt8Array(obj.Get("userEd25519Secretkey"), "constructGroupWrapper userEd"); auto user_ed25519_secretkey = toCppBuffer( obj.Get("userEd25519Secretkey"), class_name + ":constructGroupWrapper.userEd25519Secretkey"); - assertIsUInt8Array(obj.Get("groupEd25519Pubkey")); + assertIsUInt8Array(obj.Get("groupEd25519Pubkey"), "constructGroupWrapper groupEd"); auto group_ed25519_pubkey = toCppBuffer( obj.Get("groupEd25519Pubkey"), class_name + ":constructGroupWrapper.groupEd25519Pubkey"); diff --git a/src/profile_pic.cpp b/src/profile_pic.cpp index 02a55d5..14d2040 100644 --- a/src/profile_pic.cpp +++ b/src/profile_pic.cpp @@ -22,7 +22,7 @@ config::profile_pic profile_pic_from_object(Napi::Value val) { return {}; assertIsString(url); - assertIsUInt8Array(key); + assertIsUInt8Array(key, "profile_pic_from_object"); auto url_str = toCppString(url, "profile_pic_from_object"); if (url_str.size() > config::profile_pic::MAX_URL_LENGTH) diff --git a/src/user_config.cpp b/src/user_config.cpp index ce2ff7b..67e0a3c 100644 --- a/src/user_config.cpp +++ b/src/user_config.cpp @@ -71,7 +71,7 @@ void UserConfigWrapper::setUserInfo(const Napi::CallbackInfo& info) { // auto expirySeconds = info[3]; assertIsStringOrNull(name); - assertIsNumber(priority); + assertIsNumber(priority, "setUserInfo priority"); // assertIsNumber(expirySeconds); std::string new_name; diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 01124c7..02d35ca 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -130,7 +130,7 @@ void UserGroupsWrapper::setCommunityByFullUrl(const Napi::CallbackInfo& info) { toCppString(first, "group.SetCommunityByFullUrl")); auto second = info[1]; - assertIsNumber(second); + assertIsNumber(second, "setCommunityByFullUrl"); createdOrFound.priority = toPriority(second, createdOrFound.priority); config.set(createdOrFound); diff --git a/src/utilities.cpp b/src/utilities.cpp index a6341b5..ba92592 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -18,10 +18,10 @@ void assertIsStringOrNull(const Napi::Value& val) { checkOrThrow(val.IsString() || val.IsNull(), "Wrong arguments: expected string or null"); } -void assertIsNumber(const Napi::Value& val) { +void assertIsNumber(const Napi::Value& val, const std::string& identifier) { checkOrThrow( val.IsNumber() && !val.IsEmpty() && !val.IsNull() && !val.IsUndefined(), - "Wrong arguments: expected number"); + std::string("Wrong arguments: expected number" + identifier).c_str()); } void assertIsArray(const Napi::Value& val) { @@ -42,8 +42,10 @@ void assertIsUInt8ArrayOrNull(const Napi::Value& val) { checkOrThrow(val.IsNull() || IsUint8Array(val), "Wrong arguments: expected uint8Array or null"); } -void assertIsUInt8Array(const Napi::Value& val) { - checkOrThrow(IsUint8Array(val), "Wrong arguments: expected Buffer"); +void assertIsUInt8Array(const Napi::Value& val, const std::string& identifier) { + checkOrThrow( + IsUint8Array(val), + std::string("Wrong arguments: expected uint8Array" + identifier).c_str()); } void assertIsString(const Napi::Value& val) { diff --git a/src/utilities.hpp b/src/utilities.hpp index a8bd5eb..abda98f 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -26,11 +26,11 @@ void assertInfoLength(const Napi::CallbackInfo& info, const int expected); void assertInfoMinLength(const Napi::CallbackInfo& info, const int minLength); void assertIsStringOrNull(const Napi::Value& value); -void assertIsNumber(const Napi::Value& value); +void assertIsNumber(const Napi::Value& value, const std::string& identifier); void assertIsArray(const Napi::Value& value); void assertIsObject(const Napi::Value& value); void assertIsUInt8ArrayOrNull(const Napi::Value& value); -void assertIsUInt8Array(const Napi::Value& value); +void assertIsUInt8Array(const Napi::Value& value, const std::string& identifier); void assertIsString(const Napi::Value& value); void assertIsBoolean(const Napi::Value& value); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index fae4cea..0085217 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -19,5 +19,6 @@ declare module 'libsession_util_nodejs' { swarmSubAccountToken: (memberPk: PubkeyType) => string; // hex encoded swarmVerifySubAccount: (signingValue: Uint8ArrayLen100) => boolean; + loadAdminKeys: (secret: Uint8ArrayLen64) => void; }; } diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 699f6df..219728a 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -134,5 +134,6 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall; + | MakeActionCall + | MakeActionCall; } From 88557e2ecd7c36ad317abfcde3e1c3728b61ddc2 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 16 Nov 2023 16:51:07 +1100 Subject: [PATCH 32/64] feat: added kicked and invite pending group state --- src/user_groups_config.cpp | 16 +++++++++++++++- src/utilities.cpp | 12 ++++++++++++ src/utilities.hpp | 1 + types/user/usergroups.d.ts | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 02d35ca..07c31c8 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -68,7 +68,8 @@ struct toJs_impl { obj["joinedAtSeconds"] = toJs(env, info.joined_at); obj["name"] = toJs(env, info.name); obj["authData"] = toJs(env, info.auth_data); - // TODO kicked and setKicked todo + obj["invitedButNotAccepted"] = toJs(env, info.invited); + obj["kicked"] = toJs(env, info.kicked()); return obj; } @@ -309,6 +310,19 @@ Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { group_info.joined_at = *joinedAtSeconds; } + if (auto invited = maybeNonemptyBoolean( + obj.Get("invitedButNotAccepted"), + "UserGroupsWrapper::setGroup invitedButNotAccepted")) { + group_info.invited = *invited; + } + + if (auto kicked = + maybeNonemptyBoolean(obj.Get("kicked"), "UserGroupsWrapper::setGroup kicked")) { + if (*kicked) { + group_info.setKicked(); + } + } + if (auto secretKey = maybeNonemptyBuffer( obj.Get("secretKey"), "UserGroupsWrapper::setGroup secretKey")) { group_info.secretkey = *secretKey; diff --git a/src/utilities.cpp b/src/utilities.cpp index ba92592..f4d69fb 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -133,6 +133,18 @@ std::optional maybeNonemptyInt(Napi::Value x, const std::string& identi throw std::invalid_argument{"maybeNonemptyInt with invalid type, called from " + identifier}; } +std::optional maybeNonemptyBoolean(Napi::Value x, const std::string& identifier) { + if (x.IsNull() || x.IsUndefined()) + return std::nullopt; + if (x.IsBoolean()) { + + return x.As().Value(); + } + + throw std::invalid_argument{ + "maybeNonemptyBoolean with invalid type, called from " + identifier}; +} + bool toCppBoolean(Napi::Value x, const std::string& identifier) { if (x.IsNull() || x.IsUndefined()) return false; diff --git a/src/utilities.hpp b/src/utilities.hpp index abda98f..169dafd 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -56,6 +56,7 @@ ustring toCppBuffer(Napi::Value x, const std::string& identifier); ustring_view toCppBufferView(Napi::Value x, const std::string& identifier); int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUndefined = false); std::optional maybeNonemptyInt(Napi::Value x, const std::string& identifier); +std::optional maybeNonemptyBoolean(Napi::Value x, const std::string& identifier); bool toCppBoolean(Napi::Value x, const std::string& identifier); diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 35c2cb8..06bcf45 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -43,6 +43,8 @@ declare module 'libsession_util_nodejs' { secretKey: Uint8ArrayLen64 | null; // len 64 authData: Uint8ArrayLen100 | null; // len 100 name: string | null; + invitedButNotAccepted: boolean; // libsession allows this field for all groups (including communities, but we don't need it for more) + kicked: boolean; // Note: setting this to true will erase authData and admin secretKey, permanently }; /** From b48defde35ad6d12eca344d69090e988f92b1595 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 5 Dec 2023 15:33:38 +1100 Subject: [PATCH 33/64] group wip --- libsession-util | 2 +- src/user_groups_config.cpp | 5 ++--- types/user/usergroups.d.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libsession-util b/libsession-util index 20cdae8..aa6d67b 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 20cdae81cb277d9d13d86765b8bd1e14f13d9643 +Subproject commit aa6d67b3f48d0ddb98fcf678e9aab0803ba388af diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 07c31c8..89f76ec 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -68,7 +68,7 @@ struct toJs_impl { obj["joinedAtSeconds"] = toJs(env, info.joined_at); obj["name"] = toJs(env, info.name); obj["authData"] = toJs(env, info.auth_data); - obj["invitedButNotAccepted"] = toJs(env, info.invited); + obj["invitePending"] = toJs(env, info.invited); obj["kicked"] = toJs(env, info.kicked()); return obj; @@ -311,8 +311,7 @@ Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { } if (auto invited = maybeNonemptyBoolean( - obj.Get("invitedButNotAccepted"), - "UserGroupsWrapper::setGroup invitedButNotAccepted")) { + obj.Get("invitePending"), "UserGroupsWrapper::setGroup invitePending")) { group_info.invited = *invited; } diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 06bcf45..4976ba5 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -43,7 +43,7 @@ declare module 'libsession_util_nodejs' { secretKey: Uint8ArrayLen64 | null; // len 64 authData: Uint8ArrayLen100 | null; // len 100 name: string | null; - invitedButNotAccepted: boolean; // libsession allows this field for all groups (including communities, but we don't need it for more) + invitePending: boolean; // tracks `db.approved`. libsession allows this field for all groups (including communities, but we don't need it for more) kicked: boolean; // Note: setting this to true will erase authData and admin secretKey, permanently }; From 0c2261898459dd30fd1ed28b63d8615324e6a5ce Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 4 Jan 2024 16:24:02 +1100 Subject: [PATCH 34/64] fix: add back fixeduint8array type --- types/shared.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/shared.d.ts b/types/shared.d.ts index d36f1aa..b99fd62 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -1,4 +1,8 @@ declare module 'libsession_util_nodejs' { + type Uint8ArrayFixedLength = { + buffer: Uint8Array; + length: T; + }; /** * Allow a single type to be Nullable. i.e. string => string | null */ From b2cbddbd9c6b115553b56aff01a16a419e7b553e Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 10 Jan 2024 14:08:32 +1100 Subject: [PATCH 35/64] feat: add convo volatile 03group functions --- package.json | 2 +- src/convo_info_volatile_config.cpp | 66 +++++++++++++++++++++++++++++- src/convo_info_volatile_config.hpp | 6 +++ types/user/convovolatile.d.ts | 12 ++++++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 1b4870d..5a8c169 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "main": "index.js", "name": "libsession_util_nodejs", "description": "Wrappers for the Session Util Library", - "version": "0.4.1", + "version": "0.4.2", "license": "GPL-3.0", "author": { "name": "Oxen Project", diff --git a/src/convo_info_volatile_config.cpp b/src/convo_info_volatile_config.cpp index b494791..318b0b8 100644 --- a/src/convo_info_volatile_config.cpp +++ b/src/convo_info_volatile_config.cpp @@ -50,6 +50,19 @@ struct toJs_impl : toJs_impl { } }; +template <> +struct toJs_impl { + Napi::Object operator()(const Napi::Env& env, const convo::group group_info) { + auto obj = Napi::Object::New(env); + + obj["pubkeyHex"] = toJs(env, group_info.id); + obj["unread"] = toJs(env, group_info.unread); + obj["lastRead"] = toJs(env, group_info.last_read); + + return obj; + } +}; + void ConvoInfoVolatileWrapper::Init(Napi::Env env, Napi::Object exports) { InitHelper( env, @@ -69,6 +82,12 @@ void ConvoInfoVolatileWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("setLegacyGroup", &ConvoInfoVolatileWrapper::setLegacyGroup), InstanceMethod("eraseLegacyGroup", &ConvoInfoVolatileWrapper::eraseLegacyGroup), + // group related methods + InstanceMethod("getGroup", &ConvoInfoVolatileWrapper::getGroup), + InstanceMethod("getAllGroups", &ConvoInfoVolatileWrapper::getAllGroups), + InstanceMethod("setGroup", &ConvoInfoVolatileWrapper::setGroup), + InstanceMethod("eraseGroup", &ConvoInfoVolatileWrapper::eraseGroup), + // communities related methods InstanceMethod("getCommunity", &ConvoInfoVolatileWrapper::getCommunity), InstanceMethod( @@ -123,6 +142,10 @@ void ConvoInfoVolatileWrapper::set1o1(const Napi::CallbackInfo& info) { }); } +Napi::Value ConvoInfoVolatileWrapper::erase1o1(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.erase_1to1(getStringArgs<1>(info)); }); +} + /** * ================================================= * ================= Legacy groups ================= @@ -166,8 +189,47 @@ Napi::Value ConvoInfoVolatileWrapper::eraseLegacyGroup(const Napi::CallbackInfo& return wrapResult(info, [&] { return config.erase_legacy_group(getStringArgs<1>(info)); }); } -Napi::Value ConvoInfoVolatileWrapper::erase1o1(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return config.erase_1to1(getStringArgs<1>(info)); }); +/** + * ================================================= + * ===================== Groups ==================== + * ================================================= + */ + +Napi::Value ConvoInfoVolatileWrapper::getGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.get_group(getStringArgs<1>(info)); }); +} + + +Napi::Value ConvoInfoVolatileWrapper::getAllGroups(const Napi::CallbackInfo& info) { + return get_all_impl( + info, config.size_legacy_groups(), config.begin_legacy_groups(), config.end()); +} + +void ConvoInfoVolatileWrapper::setGroup(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { + assertInfoLength(info, 3); + auto first = info[0]; + assertIsString(first); + auto second = info[1]; + assertIsNumber(second, "setGroup"); + + auto third = info[2]; + assertIsBoolean(third); + + auto convo = config.get_or_construct_group(toCppString(first, "convoInfo.setGroup1")); + + if (auto last_read = toCppInteger(second, "convoInfo.setGroup2"); + last_read > convo.last_read) + convo.last_read = last_read; + + convo.unread = toCppBoolean(third, "convoInfo.setGroup3"); + + config.set(convo); + }); +} + +Napi::Value ConvoInfoVolatileWrapper::eraseGroup(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return config.erase_group(getStringArgs<1>(info)); }); } /** diff --git a/src/convo_info_volatile_config.hpp b/src/convo_info_volatile_config.hpp index 2c491fc..57191ff 100644 --- a/src/convo_info_volatile_config.hpp +++ b/src/convo_info_volatile_config.hpp @@ -29,6 +29,12 @@ class ConvoInfoVolatileWrapper : public ConfigBaseImpl, void setLegacyGroup(const Napi::CallbackInfo& info); Napi::Value eraseLegacyGroup(const Napi::CallbackInfo& info); + // group related methods + Napi::Value getGroup(const Napi::CallbackInfo& info); + Napi::Value getAllGroups(const Napi::CallbackInfo& info); + void setGroup(const Napi::CallbackInfo& info); + Napi::Value eraseGroup(const Napi::CallbackInfo& info); + // communities related methods Napi::Value getCommunity(const Napi::CallbackInfo& info); Napi::Value getAllCommunities(const Napi::CallbackInfo& info); diff --git a/types/user/convovolatile.d.ts b/types/user/convovolatile.d.ts index e7756eb..b08bfe0 100644 --- a/types/user/convovolatile.d.ts +++ b/types/user/convovolatile.d.ts @@ -1,4 +1,5 @@ /// +/// declare module 'libsession_util_nodejs' { export type ConvoVolatileType = '1o1' | UserGroupsType; @@ -10,6 +11,7 @@ declare module 'libsession_util_nodejs' { type ConvoInfoVolatile1o1 = BaseConvoInfoVolatile & { pubkeyHex: string }; type ConvoInfoVolatileLegacyGroup = BaseConvoInfoVolatile & { pubkeyHex: string }; + type ConvoInfoVolatileGroup = BaseConvoInfoVolatile & { pubkeyHex: GroupPubkeyType }; type ConvoInfoVolatileCommunity = BaseConvoInfoVolatile & CommunityDetails; // type ConvoInfoVolatileCommunity = BaseConvoInfoVolatile & { pubkeyHex: string }; // we need a `set` with the full url but maybe not for the `get` @@ -29,6 +31,12 @@ declare module 'libsession_util_nodejs' { setLegacyGroup: (pubkeyHex: string, lastRead: number, unread: boolean) => void; eraseLegacyGroup: (pubkeyHex: string) => boolean; + // group related methods + getGroup: (pubkeyHex: GroupPubkeyType) => ConvoInfoVolatileGroup | null; + getAllGroups: () => Array; + setGroup: (pubkeyHex: GroupPubkeyType, lastRead: number, unread: boolean) => void; + eraseGroup: (pubkeyHex: GroupPubkeyType) => boolean; + // communities related methods getCommunity: (communityFullUrl: string) => ConvoInfoVolatileCommunity | null; // pubkey not required getAllCommunities: () => Array; @@ -70,6 +78,10 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall From bc1d34fba85f1fd0e9aa116ec59421d943eb536e Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 18 Jan 2024 11:30:57 +1100 Subject: [PATCH 36/64] fix: fix getAllGroups returning empty array --- libsession-util | 2 +- src/convo_info_volatile_config.cpp | 4 +--- src/groups/meta_group_wrapper.cpp | 18 ++++++++++++++---- src/groups/meta_group_wrapper.hpp | 2 +- src/user_groups_config.cpp | 4 +++- types/groups/groupkeys.d.ts | 2 +- types/groups/metagroup.d.ts | 4 ++-- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libsession-util b/libsession-util index 676402b..626b662 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 676402b6ddb8ec542a7724bfa2d5f15cf33c168a +Subproject commit 626b6628a2af8fff798042416b3b469b8bfc6ecf diff --git a/src/convo_info_volatile_config.cpp b/src/convo_info_volatile_config.cpp index 318b0b8..9cf82dd 100644 --- a/src/convo_info_volatile_config.cpp +++ b/src/convo_info_volatile_config.cpp @@ -199,10 +199,8 @@ Napi::Value ConvoInfoVolatileWrapper::getGroup(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return config.get_group(getStringArgs<1>(info)); }); } - Napi::Value ConvoInfoVolatileWrapper::getAllGroups(const Napi::CallbackInfo& info) { - return get_all_impl( - info, config.size_legacy_groups(), config.begin_legacy_groups(), config.end()); + return get_all_impl(info, config.size_groups(), config.begin_groups(), config.end()); } void ConvoInfoVolatileWrapper::setGroup(const Napi::CallbackInfo& info) { diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index a662543..2e6498e 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -55,7 +55,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), - InstanceMethod("encryptMessage", &MetaGroupWrapper::encryptMessage), + InstanceMethod("encryptMessages", &MetaGroupWrapper::encryptMessages), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), InstanceMethod("makeSwarmSubAccount", &MetaGroupWrapper::makeSwarmSubAccount), InstanceMethod("swarmSubAccountToken", &MetaGroupWrapper::swarmSubAccountToken), @@ -546,12 +546,22 @@ Napi::Value MetaGroupWrapper::currentHashes(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); } -Napi::Value MetaGroupWrapper::encryptMessage(const Napi::CallbackInfo& info) { +Napi::Value MetaGroupWrapper::encryptMessages(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); + assertIsArray(info[0]); - auto plaintext = toCppBuffer(info[0], __PRETTY_FUNCTION__); - return this->meta_group->keys->encrypt_message(plaintext); + auto plaintextsJS = info[0].As(); + uint32_t arrayLength = plaintextsJS.Length(); + std::vector encryptedMessages; + encryptedMessages.reserve(arrayLength); + + for (uint32_t i = 0; i < plaintextsJS.Length(); i++) { + auto plaintext = toCppBuffer(plaintextsJS[i], __PRETTY_FUNCTION__); + + encryptedMessages.push_back(this->meta_group->keys->encrypt_message(plaintext)); + } + return encryptedMessages; }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 33b370c..733e984 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -85,7 +85,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value keyRekey(const Napi::CallbackInfo& info); Napi::Value loadKeyMessage(const Napi::CallbackInfo& info); Napi::Value currentHashes(const Napi::CallbackInfo& info); - Napi::Value encryptMessage(const Napi::CallbackInfo& info); + Napi::Value encryptMessages(const Napi::CallbackInfo& info); Napi::Value decryptMessage(const Napi::CallbackInfo& info); Napi::Value makeSwarmSubAccount(const Napi::CallbackInfo& info); Napi::Value swarmSubAccountToken(const Napi::CallbackInfo& info); diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 539aa16..9917e28 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -204,7 +204,8 @@ void UserGroupsWrapper::setLegacyGroup(const Napi::CallbackInfo& info) { group.disappearing_timer = std::chrono::seconds{toCppInteger( obj.Get("disappearingTimerSeconds"), - "legacyGroup.set disappearingTimerSeconds", true)}; + "legacyGroup.set disappearingTimerSeconds", + true)}; auto membersJSValue = obj.Get("members"); assertIsArray(membersJSValue); @@ -278,6 +279,7 @@ Napi::Value UserGroupsWrapper::getGroup(const Napi::CallbackInfo& info) { } Napi::Value UserGroupsWrapper::getAllGroups(const Napi::CallbackInfo& info) { + return get_all_impl(info, config.size_groups(), config.begin_groups(), config.end()); } diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 0085217..6e99425 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -8,7 +8,7 @@ declare module 'libsession_util_nodejs' { loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; currentHashes: () => Array; - encryptMessage: (plaintext: Uint8Array) => Uint8Array; + encryptMessages: (plaintexts: Array) => Array; decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; makeSwarmSubAccount: (memberPubkeyHex: PubkeyType) => Uint8ArrayLen100; generateSupplementKeys: (membersPubkeyHex: Array) => Array; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 219728a..c997593 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -89,7 +89,7 @@ declare module 'libsession_util_nodejs' { public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; public keyRekey: MetaGroupWrapper['keyRekey']; public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; - public encryptMessage: MetaGroupWrapper['encryptMessage']; + public encryptMessages: MetaGroupWrapper['encryptMessages']; public decryptMessage: MetaGroupWrapper['decryptMessage']; public makeSwarmSubAccount: MetaGroupWrapper['makeSwarmSubAccount']; public swarmSubaccountSign: MetaGroupWrapper['swarmSubaccountSign']; @@ -128,7 +128,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall From 420496cea8e50288a89e9dc5e45904dbfed31777 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 14 Mar 2024 15:22:52 +1100 Subject: [PATCH 37/64] feat: add keyGetAll function --- src/groups/meta_group_wrapper.cpp | 11 ++++++++++- src/groups/meta_group_wrapper.hpp | 1 + types/groups/groupkeys.d.ts | 1 + types/groups/metagroup.d.ts | 1 + types/shared.d.ts | 1 + 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 2e6498e..ce53ce8 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -51,6 +51,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), InstanceMethod("keyRekey", &MetaGroupWrapper::keyRekey), + InstanceMethod("keyGetAll", &MetaGroupWrapper::keyGetAll), InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), @@ -291,6 +292,10 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { count_merged += member_merged.size(); } + + if (this->meta_group->keys->needs_rekey()) { + this->meta_group->keys->rekey(*(this->meta_group->info), *(this->meta_group->members)); + } return count_merged; }); } @@ -526,6 +531,10 @@ Napi::Value MetaGroupWrapper::keyRekey(const Napi::CallbackInfo& info) { }); } +Napi::Value MetaGroupWrapper::keyGetAll(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { return meta_group->keys->group_keys(); }); +} + Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 3); @@ -601,7 +610,7 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf ustring subaccount = this->meta_group->keys->swarm_subaccount_token(memberPk); session::nodeapi::checkOrThrow( - subaccount.length() == 36, "expected subaccount tken to be 36 bytes long"); + subaccount.length() == 36, "expected subaccount token to be 36 bytes long"); return oxenc::to_hex(subaccount); }); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 733e984..d9ba214 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -83,6 +83,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info); Napi::Value keyRekey(const Napi::CallbackInfo& info); + Napi::Value keyGetAll(const Napi::CallbackInfo& info); Napi::Value loadKeyMessage(const Napi::CallbackInfo& info); Napi::Value currentHashes(const Napi::CallbackInfo& info); Napi::Value encryptMessages(const Napi::CallbackInfo& info); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 6e99425..c09613f 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -5,6 +5,7 @@ declare module 'libsession_util_nodejs' { // GroupKeys related methods keysNeedsRekey: () => boolean; keyRekey: () => Uint8Array; + keyGetAll: () => Array; loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; currentHashes: () => Array; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index c997593..e4a2952 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -126,6 +126,7 @@ declare module 'libsession_util_nodejs' { // keys actions | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall diff --git a/types/shared.d.ts b/types/shared.d.ts index b99fd62..04276e5 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -113,6 +113,7 @@ declare module 'libsession_util_nodejs' { export type WithPriority = { priority: number }; // -1 means hidden, 0 means normal, > 1 means pinned export type WithGroupPubkey = { groupPk: GroupPubkeyType }; + export type WithPubkey = { pubkey: PubkeyType }; type GroupInfoShared = { name: string | null; From 22e9d28795191064cb7404725f39cd9cc66d2164 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 14 Mar 2024 16:16:38 +1100 Subject: [PATCH 38/64] chore: bump libsession-util --- libsession-util | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsession-util b/libsession-util index 626b662..759dbf6 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 626b6628a2af8fff798042416b3b469b8bfc6ecf +Subproject commit 759dbf6b76a98d634d0891e19d684efa615c9a6a diff --git a/package.json b/package.json index 5a8c169..581369a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "main": "index.js", "name": "libsession_util_nodejs", "description": "Wrappers for the Session Util Library", - "version": "0.4.2", + "version": "0.4.3", "license": "GPL-3.0", "author": { "name": "Oxen Project", From 835dc91f6bc3a2068bb1aa8723811330795fd896 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 26 Mar 2024 09:23:01 +1100 Subject: [PATCH 39/64] feat: add multi encrypt/decrypt simple wrapped functions --- CMakeLists.txt | 4 +- index.d.ts | 1 + package.json | 2 +- src/addon.cpp | 4 + src/multi_encrypt/multi_encrypt.hpp | 124 +++++++++++++++++++++++++ types/multi_encrypt/index.d.ts | 2 + types/multi_encrypt/multi_encrypt.d.ts | 43 +++++++++ 7 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 src/multi_encrypt/multi_encrypt.hpp create mode 100644 types/multi_encrypt/index.d.ts create mode 100644 types/multi_encrypt/multi_encrypt.d.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index d665778..cbae385 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) # as it is not part of the archive. We actually don't care about it on session-desktop set(SUBMODULE_CHECK OFF) -file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp) +file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp src/multi_encrypt/*.cpp) add_subdirectory(libsession-util) @@ -25,7 +25,7 @@ if(MSVC) endif() add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC}) -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC} "node_modules/node-addon-api" "../../node_modules/node-addon-api") +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC} "src/" "node_modules/node-addon-api" "../../node_modules/node-addon-api") set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node") target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB} ${LIBSESSION_STATIC_BUNDLE_LIBS}) diff --git a/index.d.ts b/index.d.ts index d771f6a..e24cc9e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,7 @@ /// /// /// +/// declare module 'libsession_util_nodejs' { /** diff --git a/package.json b/package.json index 581369a..0939748 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "clang-format": "^1.8.0" }, "dependencies": { - "cmake-js": "^7.2.1", + "cmake-js": "7.2.1", "node-addon-api": "^6.1.0" }, "typings": "index.d.ts" diff --git a/src/addon.cpp b/src/addon.cpp index fce67d9..32af660 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -3,6 +3,7 @@ #include "contacts_config.hpp" #include "convo_info_volatile_config.hpp" #include "groups/meta_group_wrapper.hpp" +#include "multi_encrypt/multi_encrypt.hpp" #include "user_config.hpp" #include "user_groups_config.hpp" @@ -17,6 +18,9 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) { UserGroupsWrapper::Init(env, exports); ConvoInfoVolatileWrapper::Init(env, exports); + // Fully static wrappers init + MultiEncryptWrapper::Init(env, exports); + return exports; } diff --git a/src/multi_encrypt/multi_encrypt.hpp b/src/multi_encrypt/multi_encrypt.hpp new file mode 100644 index 0000000..d20cd58 --- /dev/null +++ b/src/multi_encrypt/multi_encrypt.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include + +#include + +#include "session/config/user_profile.hpp" +#include "session/multi_encrypt.hpp" +#include "session/random.hpp" +#include "utilities.hpp" + +namespace session::nodeapi { + +class MultiEncryptWrapper : public Napi::ObjectWrap { + + public: + MultiEncryptWrapper(const Napi::CallbackInfo& info) : + Napi::ObjectWrap{info} { + throw std::invalid_argument( + "MultiEncryptWrapper is all static and don't need to be constructed"); + } + + static void Init(Napi::Env env, Napi::Object exports) { + MetaBaseWrapper::NoBaseClassInitHelper( + env, + exports, + "MultiEncryptWrapperNode", + { + StaticMethod<&MultiEncryptWrapper::multiEncrypt>( + "multiEncrypt", + static_cast( + napi_writable | napi_configurable)), + StaticMethod<&MultiEncryptWrapper::multiDecryptEd25519>( + "multiDecryptEd25519", + static_cast( + napi_writable | napi_configurable)), + + }); + } + + private: + static Napi::Value multiEncrypt(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto obj = info[0].As(); + + if (obj.IsEmpty()) + throw std::invalid_argument("multiEncrypt received empty"); + + assertIsUInt8Array(obj.Get("ed25519SecretKey"), "multiEncrypt.ed25519SecretKey"); + auto ed25519SecretKey = + toCppBuffer(obj.Get("ed25519SecretKey"), "multiEncrypt.ed25519SecretKey"); + + assertIsString(obj.Get("domain")); + auto domain = toCppString(obj.Get("domain"), "multiEncrypt.domain"); + + // handle the messages conversion + auto messagesJSValue = obj.Get("messages"); + assertIsArray(messagesJSValue); + auto messagesJS = messagesJSValue.As(); + std::vector messages; + messages.reserve(messagesJS.Length()); + for (uint32_t i = 0; i < messagesJS.Length(); i++) { + auto itemValue = messagesJS.Get(i); + assertIsUInt8Array(itemValue, "multiEncrypt.itemValue.message"); + auto item = toCppBuffer(itemValue, "multiEncrypt.itemValue.message"); + messages.push_back(item); + } + + // handle the recipients conversion + auto recipientsJSValue = obj.Get("recipients"); + assertIsArray(recipientsJSValue); + auto recipientsJS = recipientsJSValue.As(); + std::vector recipients; + recipients.reserve(recipientsJS.Length()); + for (uint32_t i = 0; i < recipientsJS.Length(); i++) { + auto itemValue = recipientsJS.Get(i); + assertIsUInt8Array(itemValue, "multiEncrypt.itemValue.recipient"); + auto item = toCppBuffer(itemValue, "multiEncrypt.itemValue.recipient"); + recipients.push_back(item); + } + ustring random_nonce = session::random::random(24); + + std::vector messages_sv(messages.begin(), messages.end()); + std::vector recipients_sv(recipients.begin(), recipients.end()); + + // Note: this function needs the first 2 args to be vector of sv explicitely + return session::encrypt_for_multiple_simple( + messages_sv, recipients_sv, ed25519SecretKey, domain, random_nonce); + }); + }; + + static Napi::Value multiDecryptEd25519(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto obj = info[0].As(); + + if (obj.IsEmpty()) + throw std::invalid_argument("multiDecryptEd25519 received empty"); + + assertIsUInt8Array(obj.Get("encoded"), "multiDecryptEd25519.encoded"); + auto encoded = toCppBuffer(obj.Get("encoded"), "multiDecryptEd25519.encoded"); + + assertIsUInt8Array(obj.Get("ed25519SecretKey"), "multiDecryptEd25519.ed25519SecretKey"); + auto ed25519_secret_key = toCppBuffer( + obj.Get("ed25519SecretKey"), "multiDecryptEd25519.ed25519SecretKey"); + + assertIsUInt8Array( + obj.Get("senderEd25519Pubkey"), "multiDecryptEd25519.senderEd25519Pubkey"); + auto sender_ed25519_pubkey = toCppBuffer( + obj.Get("senderEd25519Pubkey"), "multiDecryptEd25519.senderEd25519Pubkey"); + + assertIsString(obj.Get("domain")); + auto domain = toCppString(obj.Get("domain"), "multiDecryptEd25519.domain"); + + return session::decrypt_for_multiple_simple_ed25519( + encoded, ed25519_secret_key, sender_ed25519_pubkey, domain); + }); + }; +}; + +} // namespace session::nodeapi diff --git a/types/multi_encrypt/index.d.ts b/types/multi_encrypt/index.d.ts new file mode 100644 index 0000000..8183bb7 --- /dev/null +++ b/types/multi_encrypt/index.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/types/multi_encrypt/multi_encrypt.d.ts b/types/multi_encrypt/multi_encrypt.d.ts new file mode 100644 index 0000000..1694655 --- /dev/null +++ b/types/multi_encrypt/multi_encrypt.d.ts @@ -0,0 +1,43 @@ +/// + +declare module 'libsession_util_nodejs' { + type MultiEncryptWrapper = { + multiEncrypt: (opts: { + /** + * len 64: ed25519 secretKey with pubkey + */ + ed25519SecretKey: Uint8ArrayLen64; + domain: string; + messages: Array; + recipients: Array; + }) => Uint8Array; + multiDecryptEd25519: (opts: { + encoded: Uint8Array; + /** + * len 64: ed25519 secretKey with pubkey + */ + ed25519SecretKey: Uint8ArrayLen64; + senderEd25519Pubkey: Uint8Array; + domain: string; + }) => Uint8Array | null; + }; + + export type MultiEncryptActionsCalls = MakeWrapperActionCalls; + + /** + * To be used inside the web worker only (calls are synchronous and won't work asynchrously) + */ + export class MultiEncryptWrapperNode { + public static multiEncrypt: MultiEncryptWrapper['multiEncrypt']; + public static multiDecryptEd25519: MultiEncryptWrapper['multiDecryptEd25519']; + } + + /** + * Those actions are used internally for the web worker communication. + * You should never need to import them in Session directly + * You will need to add an entry here if you add a new function + */ + export type MultiEncryptActionsType = + | MakeActionCall + | MakeActionCall; +} From 676c910f7812fd5394856574a648f21cedc4b575 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 16 Apr 2024 11:24:29 +1000 Subject: [PATCH 40/64] feat: add memberPendingAprovals methods --- src/groups/meta_group_wrapper.cpp | 47 ++++++++++++++++++++++++++ src/groups/meta_group_wrapper.hpp | 4 +++ types/groups/groupkeys.d.ts | 1 + types/groups/groupmembers.d.ts | 3 ++ types/groups/metagroup.d.ts | 6 ++++ types/multi_encrypt/multi_encrypt.d.ts | 4 +-- types/shared.d.ts | 3 +- 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index ce53ce8..44bd2d4 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -38,6 +38,12 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("memberGet", &MetaGroupWrapper::memberGet), InstanceMethod("memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), + InstanceMethod( + "memberGetAllPendingRemovals", + &MetaGroupWrapper::memberGetAllPendingRemovals), + InstanceMethod( + "membersMarkPendingRemoval", + &MetaGroupWrapper::membersMarkPendingRemoval), InstanceMethod("memberSetName", &MetaGroupWrapper::memberSetName), InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), InstanceMethod("memberSetAccepted", &MetaGroupWrapper::memberSetAccepted), @@ -55,6 +61,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), + InstanceMethod("keyGetCurrentGen", &MetaGroupWrapper::keyGetCurrentGen), InstanceMethod("encryptMessages", &MetaGroupWrapper::encryptMessages), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), @@ -383,6 +390,17 @@ Napi::Value MetaGroupWrapper::memberGetAll(const Napi::CallbackInfo& info) { return allMembers; }); } +Napi::Value MetaGroupWrapper::memberGetAllPendingRemovals(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + std::vector allMembersRemoved; + for (auto& member : *this->meta_group->members) { + if (member.is_removed()) { + allMembersRemoved.push_back(member); + } + } + return allMembersRemoved; + }); +} Napi::Value MetaGroupWrapper::memberGet(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { @@ -496,6 +514,28 @@ Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& }); } +Napi::Value MetaGroupWrapper::membersMarkPendingRemoval(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 2); + auto toUpdateJSValue = info[0]; + auto withMessageJSValue = info[1]; + + assertIsArray(toUpdateJSValue); + assertIsBoolean(withMessageJSValue); + bool withMessages = toCppBoolean(withMessageJSValue, __PRETTY_FUNCTION__); + + auto toUpdateJS = toUpdateJSValue.As(); + for (uint32_t i = 0; i < toUpdateJS.Length(); i++) { + auto pubkeyHex = toCppString(toUpdateJS[i], __PRETTY_FUNCTION__); + auto existing = this->meta_group->members->get_or_construct(pubkeyHex); + existing.set_removed(withMessages); + this->meta_group->members->set(existing); + } + + return true; + }); +} + Napi::Value MetaGroupWrapper::memberEraseAndRekey(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); @@ -551,6 +591,13 @@ Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { }); } +Napi::Value MetaGroupWrapper::keyGetCurrentGen(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 0); + return meta_group->keys->current_generation(); + }); +} + Napi::Value MetaGroupWrapper::currentHashes(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index d9ba214..25336e2 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -27,6 +27,7 @@ struct toJs_impl { obj["promotionFailed"] = toJs(env, info.promotion_failed()); obj["promoted"] = toJs(env, info.promoted()); obj["admin"] = toJs(env, info.admin); + obj["removedStatus"] = toJs(env, info.removed_status); return obj; } @@ -69,6 +70,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { /** Members Actions */ Napi::Value memberGetAll(const Napi::CallbackInfo& info); + Napi::Value memberGetAllPendingRemovals(const Napi::CallbackInfo& info); Napi::Value memberGet(const Napi::CallbackInfo& info); Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); Napi::Value memberSetName(const Napi::CallbackInfo& info); @@ -78,6 +80,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberSetAdmin(const Napi::CallbackInfo& info); Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info); Napi::Value memberEraseAndRekey(const Napi::CallbackInfo& info); + Napi::Value membersMarkPendingRemoval(const Napi::CallbackInfo& info); /** Keys Actions */ @@ -85,6 +88,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value keyRekey(const Napi::CallbackInfo& info); Napi::Value keyGetAll(const Napi::CallbackInfo& info); Napi::Value loadKeyMessage(const Napi::CallbackInfo& info); + Napi::Value keyGetCurrentGen(const Napi::CallbackInfo& info); Napi::Value currentHashes(const Napi::CallbackInfo& info); Napi::Value encryptMessages(const Napi::CallbackInfo& info); Napi::Value decryptMessage(const Napi::CallbackInfo& info); diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index c09613f..59fed6c 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -7,6 +7,7 @@ declare module 'libsession_util_nodejs' { keyRekey: () => Uint8Array; keyGetAll: () => Array; loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; + keyGetCurrentGen: () => number; currentHashes: () => Array; encryptMessages: (plaintexts: Array) => Array; diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 9628b77..994b4c4 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -17,6 +17,7 @@ declare module 'libsession_util_nodejs' { inviteFailed: boolean; promotionPending: boolean; promotionFailed: boolean; + removedStatus: number; // 0 = not removed, 1 means removed, 2 means removed with messages promoted: boolean; admin: boolean; }; @@ -26,6 +27,7 @@ declare module 'libsession_util_nodejs' { memberGet: (pubkeyHex: PubkeyType) => GroupMemberGet | null; memberGetOrConstruct: (pubkeyHex: PubkeyType) => GroupMemberGet; memberGetAll: () => Array; + memberGetAllPendingRemovals: () => Array; // setters memberSetName: (pubkeyHex: PubkeyType, newName: string) => GroupMemberGet; @@ -37,6 +39,7 @@ declare module 'libsession_util_nodejs' { pubkeyHex: PubkeyType, profilePicture: ProfilePicture ) => GroupMemberGet; + membersMarkPendingRemoval: (members: Array, withMessages: boolean) => boolean; // eraser memberEraseAndRekey: (members: Array) => boolean; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index e4a2952..62555f2 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -76,12 +76,14 @@ declare module 'libsession_util_nodejs' { public memberGet: MetaGroupWrapper['memberGet']; public memberGetOrConstruct: MetaGroupWrapper['memberGetOrConstruct']; public memberGetAll: MetaGroupWrapper['memberGetAll']; + public memberGetAllPendingRemovals: MetaGroupWrapper['memberGetAllPendingRemovals']; public memberSetAccepted: MetaGroupWrapper['memberSetAccepted']; public memberSetName: MetaGroupWrapper['memberSetName']; public memberSetPromoted: MetaGroupWrapper['memberSetPromoted']; public memberSetAdmin: MetaGroupWrapper['memberSetAdmin']; public memberSetInvited: MetaGroupWrapper['memberSetInvited']; public memberEraseAndRekey: MetaGroupWrapper['memberEraseAndRekey']; + public membersMarkPendingRemoval: MetaGroupWrapper['membersMarkPendingRemoval']; public memberSetProfilePicture: MetaGroupWrapper['memberSetProfilePicture']; // keys @@ -89,6 +91,7 @@ declare module 'libsession_util_nodejs' { public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; public keyRekey: MetaGroupWrapper['keyRekey']; public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; + public keyGetCurrentGen: MetaGroupWrapper['keyGetCurrentGen']; public encryptMessages: MetaGroupWrapper['encryptMessages']; public decryptMessage: MetaGroupWrapper['decryptMessage']; public makeSwarmSubAccount: MetaGroupWrapper['makeSwarmSubAccount']; @@ -115,12 +118,14 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall // keys actions @@ -128,6 +133,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall diff --git a/types/multi_encrypt/multi_encrypt.d.ts b/types/multi_encrypt/multi_encrypt.d.ts index 1694655..4ddf051 100644 --- a/types/multi_encrypt/multi_encrypt.d.ts +++ b/types/multi_encrypt/multi_encrypt.d.ts @@ -7,7 +7,7 @@ declare module 'libsession_util_nodejs' { * len 64: ed25519 secretKey with pubkey */ ed25519SecretKey: Uint8ArrayLen64; - domain: string; + domain: EncryptionDomain; messages: Array; recipients: Array; }) => Uint8Array; @@ -18,7 +18,7 @@ declare module 'libsession_util_nodejs' { */ ed25519SecretKey: Uint8ArrayLen64; senderEd25519Pubkey: Uint8Array; - domain: string; + domain: EncryptionDomain; }) => Uint8Array | null; }; diff --git a/types/shared.d.ts b/types/shared.d.ts index 04276e5..9651af5 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -126,7 +126,6 @@ declare module 'libsession_util_nodejs' { export type GroupInfoGet = GroupInfoShared & { isDestroyed: boolean; - secretKey?: Uint8ArrayLen64; // len 64 }; export type GroupInfoSet = GroupInfoShared & {}; @@ -142,4 +141,6 @@ declare module 'libsession_util_nodejs' { export type Uint8ArrayLen32 = Uint8Array; export type Uint8ArrayLen36 = Uint8Array; // subaccount tokens are 36 bytes long export type Uint8ArrayLen100 = Uint8Array; // subaccount authdata are 100 bytes long + + export type EncryptionDomain = 'SessionGroupKickedMessage'; } From 225b5ba5eb4ed0886c0d85c9685abb8c882d00ed Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 22 May 2024 10:16:29 +1000 Subject: [PATCH 41/64] feat: finished up multi encrypt/decrypt logic --- .gitignore | 4 + .yarnrc | 1 - .yarnrc.yml | 2 + package.json | 5 +- src/multi_encrypt/multi_encrypt.hpp | 5 +- src/user_config.cpp | 4 + types/groups/metagroup.d.ts | 4 +- types/multi_encrypt/multi_encrypt.d.ts | 2 +- yarn.lock | 2016 +++++++++++++++++------- 9 files changed, 1448 insertions(+), 595 deletions(-) delete mode 100644 .yarnrc create mode 100644 .yarnrc.yml diff --git a/.gitignore b/.gitignore index cd00a03..5121d16 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ /package-lock.json /compile_commands.json /.cache +.yarn/ +*.cjs +*.mjs + diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index b162bd8..0000000 --- a/.yarnrc +++ /dev/null @@ -1 +0,0 @@ ---install.frozen-lockfile true diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..ea85a0d --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,2 @@ +nodeLinker: node-modules +patchFolder: patches \ No newline at end of file diff --git a/package.json b/package.json index d3af673..17503a1 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,8 @@ "name": "Oxen Project", "email": "team@oxen.io" }, - "config": { - "electron": "25.8.4" - }, "scripts": { - "install": "cmake-js compile --runtime=electron --runtime-version=$npm_package_config_electron -p16" + "install": "cmake-js compile --runtime=electron --runtime-version=25.8.4 -p16" }, "devDependencies": { "clang-format": "^1.8.0" diff --git a/src/multi_encrypt/multi_encrypt.hpp b/src/multi_encrypt/multi_encrypt.hpp index d20cd58..4365b02 100644 --- a/src/multi_encrypt/multi_encrypt.hpp +++ b/src/multi_encrypt/multi_encrypt.hpp @@ -103,9 +103,10 @@ class MultiEncryptWrapper : public Napi::ObjectWrap { assertIsUInt8Array(obj.Get("encoded"), "multiDecryptEd25519.encoded"); auto encoded = toCppBuffer(obj.Get("encoded"), "multiDecryptEd25519.encoded"); - assertIsUInt8Array(obj.Get("ed25519SecretKey"), "multiDecryptEd25519.ed25519SecretKey"); + assertIsUInt8Array( + obj.Get("userEd25519SecretKey"), "multiDecryptEd25519.userEd25519SecretKey"); auto ed25519_secret_key = toCppBuffer( - obj.Get("ed25519SecretKey"), "multiDecryptEd25519.ed25519SecretKey"); + obj.Get("userEd25519SecretKey"), "multiDecryptEd25519.userEd25519SecretKey"); assertIsUInt8Array( obj.Get("senderEd25519Pubkey"), "multiDecryptEd25519.senderEd25519Pubkey"); diff --git a/src/user_config.cpp b/src/user_config.cpp index 7a03f91..600eea5 100644 --- a/src/user_config.cpp +++ b/src/user_config.cpp @@ -1,11 +1,15 @@ #include "user_config.hpp" +#include + #include "base_config.hpp" #include "profile_pic.hpp" +#include "session/config/base.hpp" #include "session/config/user_profile.hpp" namespace session::nodeapi { +using config::LogLevel; using config::UserProfile; void UserConfigWrapper::Init(Napi::Env env, Napi::Object exports) { diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 62555f2..24182fd 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -17,7 +17,8 @@ declare module 'libsession_util_nodejs' { GroupMemberWrapper & GroupKeysWrapper & { // shared actions - init: (options: GroupWrapperConstructor) => void; + init: (options: GroupWrapperConstructor) => void; + free: () => void; needsPush: () => boolean; push: () => { groupInfo: PushConfigResult | null; @@ -108,6 +109,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall // info actions | MakeActionCall diff --git a/types/multi_encrypt/multi_encrypt.d.ts b/types/multi_encrypt/multi_encrypt.d.ts index 4ddf051..175fb02 100644 --- a/types/multi_encrypt/multi_encrypt.d.ts +++ b/types/multi_encrypt/multi_encrypt.d.ts @@ -16,7 +16,7 @@ declare module 'libsession_util_nodejs' { /** * len 64: ed25519 secretKey with pubkey */ - ed25519SecretKey: Uint8ArrayLen64; + userEd25519SecretKey: Uint8ArrayLen64; senderEd25519Pubkey: Uint8Array; domain: EncryptionDomain; }) => Uint8Array | null; diff --git a/yarn.lock b/yarn.lock index 77f4282..690767f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,586 +1,1430 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -"aproba@^1.0.3 || ^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - -are-we-there-yet@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" - integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" - -async@^3.2.3: - version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -axios@^1.3.2: - version "1.3.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.5.tgz#e07209b39a0d11848e3e341fa087acd71dadc542" - integrity sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -clang-format@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.8.0.tgz#7779df1c5ce1bc8aac1b0b02b4e479191ef21d46" - integrity sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw== - dependencies: - async "^3.2.3" - glob "^7.0.0" - resolve "^1.1.6" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -cmake-js@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/cmake-js/-/cmake-js-7.2.1.tgz#757c0d39994121b084bab96290baf115ee7712cd" - integrity sha512-AdPSz9cSIJWdKvm0aJgVu3X8i0U3mNTswJkSHzZISqmYVjZk7Td4oDFg0mCBA383wO+9pG5Ix7pEP1CZH9x2BA== - dependencies: - axios "^1.3.2" - debug "^4" - fs-extra "^10.1.0" - lodash.isplainobject "^4.0.6" - memory-stream "^1.0.0" - node-api-headers "^0.0.2" - npmlog "^6.0.2" - rc "^1.2.7" - semver "^7.3.8" - tar "^6.1.11" - url-join "^4.0.1" - which "^2.0.2" - yargs "^17.6.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -console-control-strings@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== - -debug@^4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gauge@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" - integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.3" - console-control-strings "^1.1.0" - has-unicode "^2.0.1" - signal-exit "^3.0.7" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.5" - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -glob@^7.0.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -is-core-module@^2.11.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" - integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== - dependencies: - has "^1.0.3" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -memory-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/memory-stream/-/memory-stream-1.0.0.tgz#481dfd259ccdf57b03ec2c9632960044180e73c2" - integrity sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww== - dependencies: - readable-stream "^3.4.0" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^4.0.0: - version "4.2.8" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" - integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -node-addon-api@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" - integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== - -node-api-headers@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-0.0.2.tgz#31f4c6c2750b63e598128e76a60aefca6d76ac5d" - integrity sha512-YsjmaKGPDkmhoNKIpkChtCsPVaRE0a274IdERKnuc/E8K1UJdBZ4/mvI006OijlQZHCfpRNOH3dfHQs92se8gg== - -npmlog@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" - integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== - dependencies: - are-we-there-yet "^3.0.0" - console-control-strings "^1.1.0" - gauge "^4.0.3" - set-blocking "^2.0.0" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve@^1.1.6: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== - dependencies: - is-core-module "^2.11.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -semver@^7.3.8: - version "7.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" - integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== - dependencies: - lru-cache "^6.0.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - 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" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tar@^6.1.11: - version "6.1.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" - integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^4.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -url-join@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" - integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -which@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.6.0: - version "17.7.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" - integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: "npm:^4.3.4" + checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"aproba@npm:^1.0.3 || ^2.0.0": + version: 2.0.0 + resolution: "aproba@npm:2.0.0" + checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5 + languageName: node + linkType: hard + +"are-we-there-yet@npm:^3.0.0": + version: 3.0.1 + resolution: "are-we-there-yet@npm:3.0.1" + dependencies: + delegates: "npm:^1.0.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/8373f289ba42e4b5ec713bb585acdac14b5702c75f2a458dc985b9e4fa5762bc5b46b40a21b72418a3ed0cfb5e35bdc317ef1ae132f3035f633d581dd03168c3 + languageName: node + linkType: hard + +"async@npm:^3.2.3": + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 10c0/1408287b26c6db67d45cb346e34892cee555b8b59e6c68e6f8c3e495cad5ca13b4f218180e871f3c2ca30df4ab52693b66f2f6ff43644760cab0b2198bda79c1 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d + languageName: node + linkType: hard + +"axios@npm:^1.3.2": + version: 1.6.8 + resolution: "axios@npm:1.6.8" + dependencies: + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.0" + proxy-from-env: "npm:^1.1.0" + checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: "npm:^1.0.0" + concat-map: "npm:0.0.1" + checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.3 + resolution: "cacache@npm:18.0.3" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 10c0/dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7 + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 + languageName: node + linkType: hard + +"clang-format@npm:^1.8.0": + version: 1.8.0 + resolution: "clang-format@npm:1.8.0" + dependencies: + async: "npm:^3.2.3" + glob: "npm:^7.0.0" + resolve: "npm:^1.1.6" + bin: + check-clang-format: bin/check-clang-format.js + clang-format: index.js + git-clang-format: bin/git-clang-format + checksum: 10c0/2bd1b9bc503695e8bf9571902c94759215b72f3d0fd8379e327181dd35df8775f82e8bbc38655554d294c83fcb55c081fe3736d057606bb0d535a87d8f29860e + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 + languageName: node + linkType: hard + +"cmake-js@npm:7.2.1": + version: 7.2.1 + resolution: "cmake-js@npm:7.2.1" + dependencies: + axios: "npm:^1.3.2" + debug: "npm:^4" + fs-extra: "npm:^10.1.0" + lodash.isplainobject: "npm:^4.0.6" + memory-stream: "npm:^1.0.0" + node-api-headers: "npm:^0.0.2" + npmlog: "npm:^6.0.2" + rc: "npm:^1.2.7" + semver: "npm:^7.3.8" + tar: "npm:^6.1.11" + url-join: "npm:^4.0.1" + which: "npm:^2.0.2" + yargs: "npm:^17.6.0" + bin: + cmake-js: bin/cmake-js + checksum: 10c0/dab2fa2c04c31af90d58bdce8ad629cc35a15aac40908ab1680c0e23e752196cfdd9b0a68fc8b2f06b6fbbe7d853f4fe75d6e9b9084e26992e0270d4107e1332 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"color-support@npm:^1.1.3": + version: 1.1.3 + resolution: "color-support@npm:1.1.3" + bin: + color-support: bin.js + checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6 + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: "npm:~1.0.0" + checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f + languageName: node + linkType: hard + +"console-control-strings@npm:^1.1.0": + version: 1.1.0 + resolution: "console-control-strings@npm:1.1.0" + checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + languageName: node + linkType: hard + +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 10c0/1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 + languageName: node + linkType: hard + +"delegates@npm:^1.0.0": + version: 1.0.0 + resolution: "delegates@npm:1.0.0" + checksum: 10c0/ba05874b91148e1db4bf254750c042bf2215febd23a6d3cda2e64896aef79745fbd4b9996488bd3cafb39ce19dbce0fd6e3b6665275638befffe1c9b312b91b5 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" + peerDependenciesMeta: + debug: + optional: true + checksum: 10c0/9ff767f0d7be6aa6870c82ac79cf0368cd73e01bbc00e9eb1c2a16fbb198ec105e3c9b6628bb98e9f3ac66fe29a957b9645bcb9a490bb7aa0d35f908b6b85071 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: "npm:^7.0.0" + signal-exit: "npm:^4.0.1" + checksum: 10c0/9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 + languageName: node + linkType: hard + +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + mime-types: "npm:^2.1.12" + checksum: 10c0/cb6f3ac49180be03ff07ba3ff125f9eba2ff0b277fb33c7fc47569fc5e616882c5b1c69b9904c4c4187e97dd0419dd03b134174756f296dec62041e6527e2c6e + languageName: node + linkType: hard + +"fs-extra@npm:^10.1.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"gauge@npm:^4.0.3": + version: 4.0.4 + resolution: "gauge@npm:4.0.4" + dependencies: + aproba: "npm:^1.0.3 || ^2.0.0" + color-support: "npm:^1.1.3" + console-control-strings: "npm:^1.1.0" + has-unicode: "npm:^2.0.1" + signal-exit: "npm:^3.0.7" + string-width: "npm:^4.2.3" + strip-ansi: "npm:^6.0.1" + wide-align: "npm:^1.1.5" + checksum: 10c0/ef10d7981113d69225135f994c9f8c4369d945e64a8fc721d655a3a38421b738c9fe899951721d1b47b73c41fdb5404ac87cc8903b2ecbed95d2800363e7e58c + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.3.15 + resolution: "glob@npm:10.3.15" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.6" + minimatch: "npm:^9.0.1" + minipass: "npm:^7.0.4" + path-scurry: "npm:^1.11.0" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/cda748ddc181b31b3df9548c0991800406d5cc3b3f8110e37a8751ec1e39f37cdae7d7782d5422d7df92775121cdf00599992dff22f7ff1260344843af227c2b + languageName: node + linkType: hard + +"glob@npm:^7.0.0": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"has-unicode@npm:^2.0.1": + version: 2.0.1 + resolution: "has-unicode@npm:2.0.1" + checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 10c0/bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:^2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"ini@npm:~1.3.0": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" + dependencies: + hasown: "npm:^2.0.0" + checksum: 10c0/2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^2.3.6": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: "npm:^4.1.6" + universalify: "npm:^2.0.0" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 + languageName: node + linkType: hard + +"libsession_util_nodejs@workspace:.": + version: 0.0.0-use.local + resolution: "libsession_util_nodejs@workspace:." + dependencies: + clang-format: "npm:^1.8.0" + cmake-js: "npm:7.2.1" + node-addon-api: "npm:^6.1.0" + languageName: unknown + linkType: soft + +"lodash.isplainobject@npm:^4.0.6": + version: 4.0.6 + resolution: "lodash.isplainobject@npm:4.0.6" + checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 10c0/402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e + languageName: node + linkType: hard + +"memory-stream@npm:^1.0.0": + version: 1.0.0 + resolution: "memory-stream@npm:1.0.0" + dependencies: + readable-stream: "npm:^3.4.0" + checksum: 10c0/a2d9abd35845b228055ce5424dbdd8478711ba41325d02e6c8ef9baeba557287d4493a6e74d3db5c9849c58ea13fdc1dd445c96f469cbd02f47d22cfba930306 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + +"minimatch@npm:^3.1.1": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.1": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414 + languageName: node + linkType: hard + +"minimist@npm:^1.2.0": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": + version: 7.1.1 + resolution: "minipass@npm:7.1.1" + checksum: 10c0/fdccc2f99c31083f45f881fd1e6971d798e333e078ab3c8988fb818c470fbd5e935388ad9adb286397eba50baebf46ef8ff487c8d3f455a69c6f3efc327bdff9 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"node-addon-api@npm:^6.1.0": + version: 6.1.0 + resolution: "node-addon-api@npm:6.1.0" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/d2699c4ad15740fd31482a3b6fca789af7723ab9d393adc6ac45250faaee72edad8f0b10b2b9d087df0de93f1bdc16d97afdd179b26b9ebc9ed68b569faa4bac + languageName: node + linkType: hard + +"node-api-headers@npm:^0.0.2": + version: 0.0.2 + resolution: "node-api-headers@npm:0.0.2" + checksum: 10c0/0b1ea35d66b2be61427df8a94a0468a2979b32263fd6f4203d1e249738a89a7b6a803bd12fbe81ac731e4dab5f385968937ed4462811685700cc5b48ae316b59 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^3.0.0" + semver: "npm:^7.3.5" + tar: "npm:^6.1.2" + which: "npm:^4.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 + languageName: node + linkType: hard + +"npmlog@npm:^6.0.2": + version: 6.0.2 + resolution: "npmlog@npm:6.0.2" + dependencies: + are-we-there-yet: "npm:^3.0.0" + console-control-strings: "npm:^1.1.0" + gauge: "npm:^4.0.3" + set-blocking: "npm:^2.0.0" + checksum: 10c0/0cacedfbc2f6139c746d9cd4a85f62718435ad0ca4a2d6459cd331dd33ae58206e91a0742c1558634efcde3f33f8e8e7fd3adf1bfe7978310cf00bd55cccf890 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.0": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 10c0/f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc + languageName: node + linkType: hard + +"proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b + languageName: node + linkType: hard + +"rc@npm:^1.2.7": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: "npm:^0.6.0" + ini: "npm:~1.3.0" + minimist: "npm:^1.2.0" + strip-json-comments: "npm:~2.0.1" + bin: + rc: ./cli.js + checksum: 10c0/24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 + languageName: node + linkType: hard + +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 + languageName: node + linkType: hard + +"resolve@npm:^1.1.6": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/07e179f4375e1fd072cfb72ad66d78547f86e6196c4014b31cb0b8bb1db5f7ca871f922d08da0fbc05b94e9fd42206f819648fa3b5b873ebbc8e1dc68fec433a + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/0446f024439cd2e50c6c8fa8ba77eaa8370b4180f401a96abf3d1ebc770ac51c1955e12764cde449fde3fff480a61f84388e3505ecdbab778f4bef5f8212c729 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.5, semver@npm:^7.3.8": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 10c0/97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c + languageName: node + linkType: hard + +"set-blocking@npm:^2.0.0": + version: 2.0.0 + resolution: "set-blocking@npm:2.0.0" + checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" + dependencies: + agent-base: "npm:^7.1.1" + debug: "npm:^4.3.4" + socks: "npm:^2.7.1" + checksum: 10c0/4950529affd8ccd6951575e21c1b7be8531b24d924aa4df3ee32df506af34b618c4e50d261f4cc603f1bfd8d426915b7d629966c8ce45b05fb5ad8c8b9a6459d + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: 10c0/b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: "npm:^4.0.0" + checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 + languageName: node + linkType: hard + +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a + languageName: node + linkType: hard + +"url-join@npm:^4.0.1": + version: 4.0.1 + resolution: "url-join@npm:4.0.1" + checksum: 10c0/ac65e2c7c562d7b49b68edddcf55385d3e922bc1dd5d90419ea40b53b6de1607d1e45ceb71efb9d60da02c681d13c6cb3a1aa8b13fc0c989dfc219df97ee992d + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"which@npm:^2.0.1, which@npm:^2.0.2": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a + languageName: node + linkType: hard + +"wide-align@npm:^1.1.5": + version: 1.1.5 + resolution: "wide-align@npm:1.1.5" + dependencies: + string-width: "npm:^1.0.2 || 2 || 3 || 4" + checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 + languageName: node + linkType: hard + +"yargs@npm:^17.6.0": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 + languageName: node + linkType: hard From a8dd0e58d6ffc32f4917d25757b0cb7b9161f975 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 13 Jun 2024 13:25:12 +1000 Subject: [PATCH 42/64] fix: track hashes of all group wrappers --- src/groups/meta_group_wrapper.cpp | 11 +- src/utilities.hpp | 5 +- yarn.lock | 2007 +++++++++-------------------- 3 files changed, 591 insertions(+), 1432 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 44bd2d4..75d86b5 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -599,7 +599,16 @@ Napi::Value MetaGroupWrapper::keyGetCurrentGen(const Napi::CallbackInfo& info) { } Napi::Value MetaGroupWrapper::currentHashes(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { return meta_group->keys->current_hashes(); }); + return wrapResult(info, [&] { + auto keysHashes = meta_group->keys->current_hashes(); + auto infoHashes = meta_group->info->current_hashes(); + auto memberHashes = meta_group->members->current_hashes(); + std::vector merged; + std::copy(std::begin(keysHashes), std::end(keysHashes), std::back_inserter(merged)); + std::copy(std::begin(infoHashes), std::end(infoHashes), std::back_inserter(merged)); + std::copy(std::begin(memberHashes), std::end(memberHashes), std::back_inserter(merged)); + return merged; + }); } Napi::Value MetaGroupWrapper::encryptMessages(const Napi::CallbackInfo& info) { diff --git a/src/utilities.hpp b/src/utilities.hpp index b47853c..8a99ef7 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -3,10 +3,12 @@ #include #include +#include #include #include #include #include +#include #include "session/config/namespaces.hpp" #include "session/types.hpp" @@ -192,7 +194,8 @@ inline std::optional maybe_string(std::string_view val) { // - The return value will be returned as-is if it is already a Napi::Value (or subtype) // - The return will be void if void // - Otherwise the return value will be passed through toJs() to convert it to a Napi::Value. -// See toJs below, but generally this supports numeric types, bools, strings, ustrings, and vectors of any of those primitives. +// See toJs below, but generally this supports numeric types, bools, strings, ustrings, and vectors +// of any of those primitives. // // General use is: // diff --git a/yarn.lock b/yarn.lock index 690767f..4ce8ca3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,1430 +1,577 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 - languageName: node - linkType: hard - -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5 - languageName: node - linkType: hard - -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: "npm:^1.0.0" - readable-stream: "npm:^3.6.0" - checksum: 10c0/8373f289ba42e4b5ec713bb585acdac14b5702c75f2a458dc985b9e4fa5762bc5b46b40a21b72418a3ed0cfb5e35bdc317ef1ae132f3035f633d581dd03168c3 - languageName: node - linkType: hard - -"async@npm:^3.2.3": - version: 3.2.5 - resolution: "async@npm:3.2.5" - checksum: 10c0/1408287b26c6db67d45cb346e34892cee555b8b59e6c68e6f8c3e495cad5ca13b4f218180e871f3c2ca30df4ab52693b66f2f6ff43644760cab0b2198bda79c1 - languageName: node - linkType: hard - -"asynckit@npm:^0.4.0": - version: 0.4.0 - resolution: "asynckit@npm:0.4.0" - checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d - languageName: node - linkType: hard - -"axios@npm:^1.3.2": - version: 1.6.8 - resolution: "axios@npm:1.6.8" - dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 10c0/0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: "npm:^1.0.0" - concat-map: "npm:0.0.1" - checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"cacache@npm:^18.0.0": - version: 18.0.3 - resolution: "cacache@npm:18.0.3" - dependencies: - "@npmcli/fs": "npm:^3.1.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10c0/dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7 - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 - languageName: node - linkType: hard - -"clang-format@npm:^1.8.0": - version: 1.8.0 - resolution: "clang-format@npm:1.8.0" - dependencies: - async: "npm:^3.2.3" - glob: "npm:^7.0.0" - resolve: "npm:^1.1.6" - bin: - check-clang-format: bin/check-clang-format.js - clang-format: index.js - git-clang-format: bin/git-clang-format - checksum: 10c0/2bd1b9bc503695e8bf9571902c94759215b72f3d0fd8379e327181dd35df8775f82e8bbc38655554d294c83fcb55c081fe3736d057606bb0d535a87d8f29860e - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 - languageName: node - linkType: hard - -"cliui@npm:^8.0.1": - version: 8.0.1 - resolution: "cliui@npm:8.0.1" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.1" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 - languageName: node - linkType: hard - -"cmake-js@npm:7.2.1": - version: 7.2.1 - resolution: "cmake-js@npm:7.2.1" - dependencies: - axios: "npm:^1.3.2" - debug: "npm:^4" - fs-extra: "npm:^10.1.0" - lodash.isplainobject: "npm:^4.0.6" - memory-stream: "npm:^1.0.0" - node-api-headers: "npm:^0.0.2" - npmlog: "npm:^6.0.2" - rc: "npm:^1.2.7" - semver: "npm:^7.3.8" - tar: "npm:^6.1.11" - url-join: "npm:^4.0.1" - which: "npm:^2.0.2" - yargs: "npm:^17.6.0" - bin: - cmake-js: bin/cmake-js - checksum: 10c0/dab2fa2c04c31af90d58bdce8ad629cc35a15aac40908ab1680c0e23e752196cfdd9b0a68fc8b2f06b6fbbe7d853f4fe75d6e9b9084e26992e0270d4107e1332 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6 - languageName: node - linkType: hard - -"combined-stream@npm:^1.0.8": - version: 1.0.8 - resolution: "combined-stream@npm:1.0.8" - dependencies: - delayed-stream: "npm:~1.0.0" - checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f - languageName: node - linkType: hard - -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 - languageName: node - linkType: hard - -"deep-extend@npm:^0.6.0": - version: 0.6.0 - resolution: "deep-extend@npm:0.6.0" - checksum: 10c0/1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 - languageName: node - linkType: hard - -"delayed-stream@npm:~1.0.0": - version: 1.0.0 - resolution: "delayed-stream@npm:1.0.0" - checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 - languageName: node - linkType: hard - -"delegates@npm:^1.0.0": - version: 1.0.0 - resolution: "delegates@npm:1.0.0" - checksum: 10c0/ba05874b91148e1db4bf254750c042bf2215febd23a6d3cda2e64896aef79745fbd4b9996488bd3cafb39ce19dbce0fd6e3b6665275638befffe1c9b312b91b5 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.1.2 - resolution: "escalade@npm:3.1.2" - checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.15.6": - version: 1.15.6 - resolution: "follow-redirects@npm:1.15.6" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/9ff767f0d7be6aa6870c82ac79cf0368cd73e01bbc00e9eb1c2a16fbb198ec105e3c9b6628bb98e9f3ac66fe29a957b9645bcb9a490bb7aa0d35f908b6b85071 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" - dependencies: - cross-spawn: "npm:^7.0.0" - signal-exit: "npm:^4.0.1" - checksum: 10c0/9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 - languageName: node - linkType: hard - -"form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - mime-types: "npm:^2.1.12" - checksum: 10c0/cb6f3ac49180be03ff07ba3ff125f9eba2ff0b277fb33c7fc47569fc5e616882c5b1c69b9904c4c4187e97dd0419dd03b134174756f296dec62041e6527e2c6e - languageName: node - linkType: hard - -"fs-extra@npm:^10.1.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: "npm:^1.0.3 || ^2.0.0" - color-support: "npm:^1.1.3" - console-control-strings: "npm:^1.1.0" - has-unicode: "npm:^2.0.1" - signal-exit: "npm:^3.0.7" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - wide-align: "npm:^1.1.5" - checksum: 10c0/ef10d7981113d69225135f994c9f8c4369d945e64a8fc721d655a3a38421b738c9fe899951721d1b47b73c41fdb5404ac87cc8903b2ecbed95d2800363e7e58c - languageName: node - linkType: hard - -"get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.15 - resolution: "glob@npm:10.3.15" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.6" - minimatch: "npm:^9.0.1" - minipass: "npm:^7.0.4" - path-scurry: "npm:^1.11.0" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/cda748ddc181b31b3df9548c0991800406d5cc3b3f8110e37a8751ec1e39f37cdae7d7782d5422d7df92775121cdf00599992dff22f7ff1260344843af227c2b - languageName: node - linkType: hard - -"glob@npm:^7.0.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c - languageName: node - linkType: hard - -"hasown@npm:^2.0.0": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" - dependencies: - agent-base: "npm:^7.0.2" - debug: "npm:4" - checksum: 10c0/bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:^2.0.3": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"ini@npm:~1.3.0": - version: 1.3.8 - resolution: "ini@npm:1.3.8" - checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-core-module@npm:^2.13.0": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" - dependencies: - hasown: "npm:^2.0.0" - checksum: 10c0/2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^2.3.6": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" - dependencies: - graceful-fs: "npm:^4.1.6" - universalify: "npm:^2.0.0" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 - languageName: node - linkType: hard - -"libsession_util_nodejs@workspace:.": - version: 0.0.0-use.local - resolution: "libsession_util_nodejs@workspace:." - dependencies: - clang-format: "npm:^1.8.0" - cmake-js: "npm:7.2.1" - node-addon-api: "npm:^6.1.0" - languageName: unknown - linkType: soft - -"lodash.isplainobject@npm:^4.0.6": - version: 4.0.6 - resolution: "lodash.isplainobject@npm:4.0.6" - checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.2 - resolution: "lru-cache@npm:10.2.2" - checksum: 10c0/402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^13.0.0": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" - dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" - http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e - languageName: node - linkType: hard - -"memory-stream@npm:^1.0.0": - version: 1.0.0 - resolution: "memory-stream@npm:1.0.0" - dependencies: - readable-stream: "npm:^3.4.0" - checksum: 10c0/a2d9abd35845b228055ce5424dbdd8478711ba41325d02e6c8ef9baeba557287d4493a6e74d3db5c9849c58ea13fdc1dd445c96f469cbd02f47d22cfba930306 - languageName: node - linkType: hard - -"mime-db@npm:1.52.0": - version: 1.52.0 - resolution: "mime-db@npm:1.52.0" - checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa - languageName: node - linkType: hard - -"mime-types@npm:^2.1.12": - version: 2.1.35 - resolution: "mime-types@npm:2.1.35" - dependencies: - mime-db: "npm:1.52.0" - checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 - languageName: node - linkType: hard - -"minimatch@npm:^3.1.1": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.1": - version: 9.0.4 - resolution: "minimatch@npm:9.0.4" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414 - languageName: node - linkType: hard - -"minimist@npm:^1.2.0": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": - version: 7.1.1 - resolution: "minipass@npm:7.1.1" - checksum: 10c0/fdccc2f99c31083f45f881fd1e6971d798e333e078ab3c8988fb818c470fbd5e935388ad9adb286397eba50baebf46ef8ff487c8d3f455a69c6f3efc327bdff9 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc - languageName: node - linkType: hard - -"negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 - languageName: node - linkType: hard - -"node-addon-api@npm:^6.1.0": - version: 6.1.0 - resolution: "node-addon-api@npm:6.1.0" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/d2699c4ad15740fd31482a3b6fca789af7723ab9d393adc6ac45250faaee72edad8f0b10b2b9d087df0de93f1bdc16d97afdd179b26b9ebc9ed68b569faa4bac - languageName: node - linkType: hard - -"node-api-headers@npm:^0.0.2": - version: 0.0.2 - resolution: "node-api-headers@npm:0.0.2" - checksum: 10c0/0b1ea35d66b2be61427df8a94a0468a2979b32263fd6f4203d1e249738a89a7b6a803bd12fbe81ac731e4dab5f385968937ed4462811685700cc5b48ae316b59 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 10.1.0 - resolution: "node-gyp@npm:10.1.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^3.0.0" - semver: "npm:^7.3.5" - tar: "npm:^6.1.2" - which: "npm:^4.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c - languageName: node - linkType: hard - -"nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" - dependencies: - abbrev: "npm:^2.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 - languageName: node - linkType: hard - -"npmlog@npm:^6.0.2": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: "npm:^3.0.0" - console-control-strings: "npm:^1.1.0" - gauge: "npm:^4.0.3" - set-blocking: "npm:^2.0.0" - checksum: 10c0/0cacedfbc2f6139c746d9cd4a85f62718435ad0ca4a2d6459cd331dd33ae58206e91a0742c1558634efcde3f33f8e8e7fd3adf1bfe7978310cf00bd55cccf890 - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.0": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"proc-log@npm:^3.0.0": - version: 3.0.0 - resolution: "proc-log@npm:3.0.0" - checksum: 10c0/f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc - languageName: node - linkType: hard - -"proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b - languageName: node - linkType: hard - -"rc@npm:^1.2.7": - version: 1.2.8 - resolution: "rc@npm:1.2.8" - dependencies: - deep-extend: "npm:^0.6.0" - ini: "npm:~1.3.0" - minimist: "npm:^1.2.0" - strip-json-comments: "npm:~2.0.1" - bin: - rc: ./cli.js - checksum: 10c0/24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 - languageName: node - linkType: hard - -"readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"resolve@npm:^1.1.6": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/07e179f4375e1fd072cfb72ad66d78547f86e6196c4014b31cb0b8bb1db5f7ca871f922d08da0fbc05b94e9fd42206f819648fa3b5b873ebbc8e1dc68fec433a - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/0446f024439cd2e50c6c8fa8ba77eaa8370b4180f401a96abf3d1ebc770ac51c1955e12764cde449fde3fff480a61f84388e3505ecdbab778f4bef5f8212c729 - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5, semver@npm:^7.3.8": - version: 7.6.2 - resolution: "semver@npm:7.6.2" - bin: - semver: bin/semver.js - checksum: 10c0/97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c - languageName: node - linkType: hard - -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^3.0.7": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.3 - resolution: "socks-proxy-agent@npm:8.0.3" - dependencies: - agent-base: "npm:^7.1.1" - debug: "npm:^4.3.4" - socks: "npm:^2.7.1" - checksum: 10c0/4950529affd8ccd6951575e21c1b7be8531b24d924aa4df3ee32df506af34b618c4e50d261f4cc603f1bfd8d426915b7d629966c8ce45b05fb5ad8c8b9a6459d - languageName: node - linkType: hard - -"socks@npm:^2.7.1": - version: 2.8.3 - resolution: "socks@npm:2.8.3" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^10.0.0": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"strip-json-comments@npm:~2.0.1": - version: 2.0.1 - resolution: "strip-json-comments@npm:2.0.1" - checksum: 10c0/b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 - languageName: node - linkType: hard - -"tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 - languageName: node - linkType: hard - -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f - languageName: node - linkType: hard - -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 - languageName: node - linkType: hard - -"universalify@npm:^2.0.0": - version: 2.0.1 - resolution: "universalify@npm:2.0.1" - checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a - languageName: node - linkType: hard - -"url-join@npm:^4.0.1": - version: 4.0.1 - resolution: "url-join@npm:4.0.1" - checksum: 10c0/ac65e2c7c562d7b49b68edddcf55385d3e922bc1dd5d90419ea40b53b6de1607d1e45ceb71efb9d60da02c681d13c6cb3a1aa8b13fc0c989dfc219df97ee992d - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 - languageName: node - linkType: hard - -"which@npm:^2.0.1, which@npm:^2.0.2": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a - languageName: node - linkType: hard - -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" - dependencies: - string-width: "npm:^1.0.2 || 2 || 3 || 4" - checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 - languageName: node - linkType: hard - -"yargs@npm:^17.6.0": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 - languageName: node - linkType: hard +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +async@^3.2.3: + version "3.2.5" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" + integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.3.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +clang-format@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.8.0.tgz#7779df1c5ce1bc8aac1b0b02b4e479191ef21d46" + integrity sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw== + dependencies: + async "^3.2.3" + glob "^7.0.0" + resolve "^1.1.6" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +cmake-js@7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/cmake-js/-/cmake-js-7.2.1.tgz#757c0d39994121b084bab96290baf115ee7712cd" + integrity sha512-AdPSz9cSIJWdKvm0aJgVu3X8i0U3mNTswJkSHzZISqmYVjZk7Td4oDFg0mCBA383wO+9pG5Ix7pEP1CZH9x2BA== + dependencies: + axios "^1.3.2" + debug "^4" + fs-extra "^10.1.0" + lodash.isplainobject "^4.0.6" + memory-stream "^1.0.0" + node-api-headers "^0.0.2" + npmlog "^6.0.2" + rc "^1.2.7" + semver "^7.3.8" + tar "^6.1.11" + url-join "^4.0.1" + which "^2.0.2" + yargs "^17.6.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +debug@^4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob@^7.0.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +memory-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-stream/-/memory-stream-1.0.0.tgz#481dfd259ccdf57b03ec2c9632960044180e73c2" + integrity sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww== + dependencies: + readable-stream "^3.4.0" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +node-addon-api@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" + integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== + +node-api-headers@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-0.0.2.tgz#31f4c6c2750b63e598128e76a60aefca6d76ac5d" + integrity sha512-YsjmaKGPDkmhoNKIpkChtCsPVaRE0a274IdERKnuc/E8K1UJdBZ4/mvI006OijlQZHCfpRNOH3dfHQs92se8gg== + +npmlog@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve@^1.1.6: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^7.3.8: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + 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" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.6.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" From 25138206c51e523a378867a0a76a96bd2ea1f14b Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 13 Jun 2024 13:25:51 +1000 Subject: [PATCH 43/64] fix: gen supplemental keys once for all new members --- src/groups/meta_group_wrapper.cpp | 8 ++++---- types/groups/groupkeys.d.ts | 2 +- types/groups/groupmembers.d.ts | 7 ++++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 75d86b5..b35c766 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -704,14 +704,14 @@ Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& i uint32_t arrayLength = membersJS.Length(); std::vector membersToAdd; membersToAdd.reserve(arrayLength); - std::vector keyMessages; - keyMessages.reserve(arrayLength); + std::vector membersCpp; + membersCpp.reserve(arrayLength); for (uint32_t i = 0; i < membersJS.Length(); i++) { auto memberPk = toCppString(membersJS[i], __PRETTY_FUNCTION__); - keyMessages.push_back(this->meta_group->keys->key_supplement(memberPk)); + membersCpp.push_back(memberPk); } - return keyMessages; + return this->meta_group->keys->key_supplement(membersCpp); }); } diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 59fed6c..3865f67 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -13,7 +13,7 @@ declare module 'libsession_util_nodejs' { encryptMessages: (plaintexts: Array) => Array; decryptMessage: (ciphertext: Uint8Array) => { pubkeyHex: string; plaintext: Uint8Array }; makeSwarmSubAccount: (memberPubkeyHex: PubkeyType) => Uint8ArrayLen100; - generateSupplementKeys: (membersPubkeyHex: Array) => Array; + generateSupplementKeys: (membersPubkeyHex: Array) => Uint8Array; swarmSubaccountSign: ( message: Uint8Array, authData: Uint8ArrayLen100 diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 994b4c4..8adb848 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -17,7 +17,12 @@ declare module 'libsession_util_nodejs' { inviteFailed: boolean; promotionPending: boolean; promotionFailed: boolean; - removedStatus: number; // 0 = not removed, 1 means removed, 2 means removed with messages + /** + * - 0 means not removed, + * - 1 means removed (libsession: REMOVED_MEMBER), + * - 2 means removed with messages (libsession: REMOVED_MEMBER_AND_MESSAGES) + */ + removedStatus: number; promoted: boolean; admin: boolean; }; From 3bcae62ed412d5eb6594884b7d2c8d15b30a9816 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 14 Jun 2024 09:41:37 +1000 Subject: [PATCH 44/64] feat: update libsession-util to latest dev --- libsession-util | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsession-util b/libsession-util index 759dbf6..9e6e7c9 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 759dbf6b76a98d634d0891e19d684efa615c9a6a +Subproject commit 9e6e7c989dbe6b9deeaaab592c590b6c287eeaa3 From 156f340ae05e1ba94c0bd87c8a63b9d3654c96bb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 28 Jun 2024 13:39:17 +1000 Subject: [PATCH 45/64] fix: test with libsession-util not of libquic --- .github/workflows/test.yml | 1 + CMakeLists.txt | 14 +++++++++ libsession-util | 2 +- package.json | 2 +- src/base_config.hpp | 23 +++++++------- src/groups/meta_group_wrapper.cpp | 51 +++++++++++++++++++++++++++++-- src/user_config.cpp | 2 +- 7 files changed, 79 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e371f2e..11e6872 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - groups-chunk-2 concurrency: group: ${{ github.workflow }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c3ba33..bc8cdb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,20 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(VERBOSE ON) +# Detect the number of processors +include(ProcessorCount) +ProcessorCount(N) + +# Set a default value in case the detection fails +if(NOT N EQUAL 0) + set(CMAKE_BUILD_PARALLEL_LEVEL ${N}) +else() + set(CMAKE_BUILD_PARALLEL_LEVEL 4) # Fallback to 16 if detection fails +endif() +# set(CMAKE_BUILD_PARALLEL_LEVEL 32) +message(STATUS "Number of processors detected: ${N}") + + add_definitions(-DNAPI_VERSION=8) set(CMAKE_CONFIGURATION_TYPES Release) diff --git a/libsession-util b/libsession-util index 20c0667..47b6920 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 20c06674d85369c2d12261582dd36a9f21504233 +Subproject commit 47b6920c5c0862bac39180ac95bf11981ba0bdb5 diff --git a/package.json b/package.json index ac5073e..ee5391b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "email": "team@oxen.io" }, "scripts": { - "install": "cmake-js compile --runtime=electron --runtime-version=25.8.4 -p16 --CDSUBMODULE_CHECK=OFF --CDLOCAL_MIRROR=https://oxen.rocks/deps --CDENABLE_ONIONREQ=OFF" + "install": "cmake-js compile --runtime=electron --runtime-version=25.8.4 --CDLOCAL_MIRROR=https://oxen.rocks/deps --CDENABLE_ONIONREQ=OFF" }, "devDependencies": { "clang-format": "^1.8.0" diff --git a/src/base_config.hpp b/src/base_config.hpp index 6eeebdb..5119cb2 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -106,17 +106,18 @@ class ConfigBaseImpl { Napi::Env env = info.Env(); - config->logger = [env, class_name](session::config::LogLevel, std::string_view x) { - std::string toLog = - "libsession-util:" + std::string(class_name) + ": " + std::string(x) + "\n"; - - Napi::Function consoleLog = env.Global() - .Get("console") - .As() - .Get("log") - .As(); - consoleLog.Call({Napi::String::New(env, toLog)}); - }; + // config->logger = [env, class_name](session::config::LogLevel, std::string_view x) { + // std::string toLog = + // "libsession-util:" + std::string(class_name) + ": " + std::string(x) + + // "\n"; + + // Napi::Function consoleLog = env.Global() + // .Get("console") + // .As() + // .Get("log") + // .As(); + // consoleLog.Call({Napi::String::New(env, toLog)}); + // }; return config; }); diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index b35c766..fee8087 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -11,7 +11,32 @@ namespace session::nodeapi { MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : meta_group{std::move(MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper"))}, - Napi::ObjectWrap{info} {} + Napi::ObjectWrap{info} { + auto env = info.Env(); + // this->meta_group->members->logger = [env](session::config::LogLevel, std::string_view x) { + // std::string toLog = "libsession-util:MetaGroup:Member: " + std::string(x) + "\n"; + + // Napi::Function consoleLog = + // env.Global().Get("console").As().Get("log").As(); + // consoleLog.Call({Napi::String::New(env, toLog)}); + // }; + // this->meta_group->info->logger = [env](session::config::LogLevel, std::string_view x) { + // std::string toLog = "libsession-util:MetaGroup:Info: " + std::string(x) + "\n"; + + // Napi::Function consoleLog = + // env.Global().Get("console").As().Get("log").As(); + // consoleLog.Call({Napi::String::New(env, toLog)}); + // }; + // this->meta_group->keys->logger = [env]( + // session::config::LogLevel, + // std::string_view x) { + // std::string toLog = "libsession-util:MetaGroup:Keys: " + std::string(x) + "\n"; + + // Napi::Function consoleLog = + // env.Global().Get("console").As().Get("log").As(); + // consoleLog.Call({Napi::String::New(env, toLog)}); + // }; +} void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { MetaBaseWrapper::NoBaseClassInitHelper( @@ -445,9 +470,31 @@ Napi::Value MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); auto m = this->meta_group->members->get_or_construct(pubkeyHex); + + // this->meta_group->members->log( + // session::config::LogLevel::warning, + // "libsession-util before: needsDump? " + + // std::string(this->needsDump(info) ? "true" : "false")); + // this->meta_group->members->log( + // session::config::LogLevel::warning, + // "libsession-util before: invite_failed of " + std::string(pubkeyHex) + + // " val: " + std::string(m.invite_failed() ? "true" : "false")); m.set_invited(failed); this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + // this->meta_group->members->log( + // session::config::LogLevel::warning, + // "libsession-util after: invite_failed of " + std::string(pubkeyHex) + + // " val: " + std::string(m.invite_failed() ? "true" : "false")); + auto refreshed = this->meta_group->members->get_or_construct(m.session_id); + // this->meta_group->members->log( + // session::config::LogLevel::warning, + // "libsession-util refreshed: invite_failed of " + std::string(pubkeyHex) + + // " val: " + std::string(refreshed.invite_failed() ? "true" : "false")); + // this->meta_group->members->log( + // session::config::LogLevel::warning, + // "libsession-util after: needsDump? of " + + // std::string(this->needsDump(info) ? "true" : "false")); + return refreshed; }); } diff --git a/src/user_config.cpp b/src/user_config.cpp index 600eea5..4508ead 100644 --- a/src/user_config.cpp +++ b/src/user_config.cpp @@ -9,7 +9,7 @@ namespace session::nodeapi { -using config::LogLevel; +// using config::LogLevel; using config::UserProfile; void UserConfigWrapper::Init(Napi::Env env, Napi::Object exports) { From 50b9a31d3325f2843e11753f601f8039f79932d0 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 28 Jun 2024 14:42:41 +1000 Subject: [PATCH 46/64] fix: fix build without onionreq --- .github/workflows/test.yml | 26 ++++++++++++++++++++++++-- CMakeLists.txt | 2 +- libsession-util | 2 +- package.json | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 11e6872..88963db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,10 +14,14 @@ concurrency: jobs: build: runs-on: ${{ matrix.os }} + strategy: fail-fast: false + + matrix: - os: [windows-2022, macos-11, ubuntu-20.04] + os: [windows-latest, macos-latest, ubuntu-latest] + env: SIGNAL_ENV: production GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -29,6 +33,16 @@ jobs: with: submodules: 'recursive' + # this should only be needed on ubuntu-20.04 + + # - name: Force g++10 to be used + # if: runner.os == 'Linux' + # shell: bash + # run: | + # sudo apt install -y libstdc++-10-dev g++-10 + # sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10 + # sudo update-alternatives --set gcc /usr/bin/gcc-10 + - name: Install node uses: actions/setup-node@v3 with: @@ -48,6 +62,14 @@ jobs: run: | yarn global add node-gyp@latest + - name: sed it + if: runner.os == 'Windows' + shell: bash + run: | + sed -i "s/target_compile_options(oxen-logging-warnings INTERFACE/#target_compile_options(oxen-logging-warnings INTERFACE/" libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt + cat libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt + + - name: build libsession-util-nodejs shell: bash - run: yarn install --frozen-lockfile --network-timeout 600000 + run: yarn install --frozen-lockfile diff --git a/CMakeLists.txt b/CMakeLists.txt index bc8cdb9..46176e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ SET(CMAKE_EXPORT_COMPILE_COMMANDS ON) SET(CMAKE_BUILD_TYPE Release) SET(WITH_TESTS OFF) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/libsession-util b/libsession-util index 47b6920..0faee84 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 47b6920c5c0862bac39180ac95bf11981ba0bdb5 +Subproject commit 0faee8459c3c2f76c527a050a7b7fe3b0e844165 diff --git a/package.json b/package.json index ee5391b..ba0c0f7 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "email": "team@oxen.io" }, "scripts": { - "install": "cmake-js compile --runtime=electron --runtime-version=25.8.4 --CDLOCAL_MIRROR=https://oxen.rocks/deps --CDENABLE_ONIONREQ=OFF" + "install": "cmake-js compile --runtime=electron --runtime-version=25.8.4 --CDLOCAL_MIRROR=https://oxen.rocks/deps --CDENABLE_ONIONREQ=OFF --CDWITH_TESTS=OFF" }, "devDependencies": { "clang-format": "^1.8.0" From f4985cc884885a614f9f3dcfbf62b95888e204f3 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 3 Jul 2024 11:53:04 +1000 Subject: [PATCH 47/64] feat: keep groupPk/secKey in metagroup for debugging purposes if needed --- .yarnrc.yml | 3 ++- CMakeLists.txt | 1 - src/groups/meta_group.hpp | 12 ++++++++++-- src/groups/meta_group_wrapper.cpp | 27 ++++----------------------- src/meta/meta_base_wrapper.hpp | 2 +- 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/.yarnrc.yml b/.yarnrc.yml index ea85a0d..5fdaec4 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1,2 +1,3 @@ nodeLinker: node-modules -patchFolder: patches \ No newline at end of file + +patchFolder: patches diff --git a/CMakeLists.txt b/CMakeLists.txt index 46176e9..bb8c33a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ if(NOT N EQUAL 0) else() set(CMAKE_BUILD_PARALLEL_LEVEL 4) # Fallback to 16 if detection fails endif() -# set(CMAKE_BUILD_PARALLEL_LEVEL 32) message(STATUS "Number of processors detected: ${N}") diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index b557988..231a931 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -25,12 +25,20 @@ class MetaGroup { shared_ptr info; shared_ptr members; shared_ptr keys; + string edGroupPubKey; + std::optional edGroupSecKey; MetaGroup( shared_ptr info, shared_ptr members, - shared_ptr keys) : - info{info}, members{members}, keys{keys} {}; + shared_ptr keys, + session::ustring edGroupPubKey, + std::optional edGroupSecKey) : + info{info}, members{members}, keys{keys} { + + this->edGroupPubKey = oxenc::to_hex(edGroupPubKey); + this->edGroupSecKey = edGroupSecKey ? oxenc::to_hex(*edGroupSecKey) : nullptr; + }; explicit MetaGroup(const Napi::CallbackInfo& info) {} }; diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index fee8087..bb45b97 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -469,32 +469,13 @@ Napi::Value MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { assertIsBoolean(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - // this->meta_group->members->log( - // session::config::LogLevel::warning, - // "libsession-util before: needsDump? " + - // std::string(this->needsDump(info) ? "true" : "false")); - // this->meta_group->members->log( - // session::config::LogLevel::warning, - // "libsession-util before: invite_failed of " + std::string(pubkeyHex) + - // " val: " + std::string(m.invite_failed() ? "true" : "false")); + auto m = this->meta_group->members->get_or_construct(pubkeyHex); m.set_invited(failed); this->meta_group->members->set(m); - // this->meta_group->members->log( - // session::config::LogLevel::warning, - // "libsession-util after: invite_failed of " + std::string(pubkeyHex) + - // " val: " + std::string(m.invite_failed() ? "true" : "false")); - auto refreshed = this->meta_group->members->get_or_construct(m.session_id); - // this->meta_group->members->log( - // session::config::LogLevel::warning, - // "libsession-util refreshed: invite_failed of " + std::string(pubkeyHex) + - // " val: " + std::string(refreshed.invite_failed() ? "true" : "false")); - // this->meta_group->members->log( - // session::config::LogLevel::warning, - // "libsession-util after: needsDump? of " + - // std::string(this->needsDump(info) ? "true" : "false")); - return refreshed; + + return this->meta_group->members->get_or_construct(pubkeyHex); + }); } diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 73ee4ab..01082dc 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -101,7 +101,7 @@ class MetaBaseWrapper { *info, *members); - return std::make_unique(info, members, keys); + return std::make_unique(info, members, keys,group_ed25519_pubkey, group_ed25519_secretkey); }); } }; From 737a3e4b385e94eb8c57b8d4ea0b54a6cfaf302d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 5 Jul 2024 13:22:47 +1000 Subject: [PATCH 48/64] bump libsesison-util with dirty hack to make dump work as expected --- libsession-util | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsession-util b/libsession-util index 0faee84..cffdbde 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 0faee8459c3c2f76c527a050a7b7fe3b0e844165 +Subproject commit cffdbde7061b935397c69ab816910228ddf5cb12 From 945b66d1956c5cab677107b3622a46a6ae89f6bf Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 8 Jul 2024 11:28:35 +1000 Subject: [PATCH 49/64] feat: add keys for group when provided for easier debugging --- src/groups/meta_group.hpp | 18 ++++++++-------- src/groups/meta_group_wrapper.cpp | 35 +------------------------------ src/meta/meta_base_wrapper.hpp | 4 +++- src/utilities.hpp | 1 - 4 files changed, 13 insertions(+), 45 deletions(-) diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index 231a931..a11d7be 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -34,13 +34,13 @@ class MetaGroup { shared_ptr keys, session::ustring edGroupPubKey, std::optional edGroupSecKey) : - info{info}, members{members}, keys{keys} { - - this->edGroupPubKey = oxenc::to_hex(edGroupPubKey); - this->edGroupSecKey = edGroupSecKey ? oxenc::to_hex(*edGroupSecKey) : nullptr; - }; - - explicit MetaGroup(const Napi::CallbackInfo& info) {} + info{info}, members{members}, keys{keys}, edGroupPubKey{oxenc::to_hex(edGroupPubKey)} { + + if (edGroupSecKey.has_value()) { + this->edGroupSecKey = oxenc::to_hex(*edGroupSecKey); + } else { + this->edGroupSecKey = std::nullopt; + } + } }; - -} // namespace session::nodeapi +} // namespace session::nodeapi \ No newline at end of file diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index bb45b97..925e0c9 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -11,32 +11,7 @@ namespace session::nodeapi { MetaGroupWrapper::MetaGroupWrapper(const Napi::CallbackInfo& info) : meta_group{std::move(MetaBaseWrapper::constructGroupWrapper(info, "MetaGroupWrapper"))}, - Napi::ObjectWrap{info} { - auto env = info.Env(); - // this->meta_group->members->logger = [env](session::config::LogLevel, std::string_view x) { - // std::string toLog = "libsession-util:MetaGroup:Member: " + std::string(x) + "\n"; - - // Napi::Function consoleLog = - // env.Global().Get("console").As().Get("log").As(); - // consoleLog.Call({Napi::String::New(env, toLog)}); - // }; - // this->meta_group->info->logger = [env](session::config::LogLevel, std::string_view x) { - // std::string toLog = "libsession-util:MetaGroup:Info: " + std::string(x) + "\n"; - - // Napi::Function consoleLog = - // env.Global().Get("console").As().Get("log").As(); - // consoleLog.Call({Napi::String::New(env, toLog)}); - // }; - // this->meta_group->keys->logger = [env]( - // session::config::LogLevel, - // std::string_view x) { - // std::string toLog = "libsession-util:MetaGroup:Keys: " + std::string(x) + "\n"; - - // Napi::Function consoleLog = - // env.Global().Get("console").As().Get("log").As(); - // consoleLog.Call({Napi::String::New(env, toLog)}); - // }; -} + Napi::ObjectWrap{info} {} void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { MetaBaseWrapper::NoBaseClassInitHelper( @@ -152,8 +127,6 @@ Napi::Value MetaGroupWrapper::needsDump(const Napi::CallbackInfo& info) { Napi::Value MetaGroupWrapper::metaDump(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - auto env = info.Env(); - oxenc::bt_dict_producer combined; // NOTE: the keys have to be in ascii-sorted order: @@ -168,8 +141,6 @@ Napi::Value MetaGroupWrapper::metaDump(const Napi::CallbackInfo& info) { Napi::Value MetaGroupWrapper::metaMakeDump(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - auto env = info.Env(); - oxenc::bt_dict_producer combined; // NOTE: the keys have to be in ascii-sorted order: @@ -192,7 +163,6 @@ void MetaGroupWrapper::metaConfirmPushed(const Napi::CallbackInfo& info) { auto groupInfo = obj.Get("groupInfo"); auto groupMember = obj.Get("groupMember"); - auto groupKeys = obj.Get("groupKeys"); if (!groupInfo.IsNull() && !groupInfo.IsUndefined()) { assertIsArray(groupInfo); @@ -429,7 +399,6 @@ Napi::Value MetaGroupWrapper::memberGetAllPendingRemovals(const Napi::CallbackIn Napi::Value MetaGroupWrapper::memberGet(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - auto env = info.Env(); assertInfoLength(info, 1); assertIsString(info[0]); @@ -440,7 +409,6 @@ Napi::Value MetaGroupWrapper::memberGet(const Napi::CallbackInfo& info) { Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { - auto env = info.Env(); assertInfoLength(info, 1); assertIsString(info[0]); @@ -475,7 +443,6 @@ Napi::Value MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { this->meta_group->members->set(m); return this->meta_group->members->get_or_construct(pubkeyHex); - }); } diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 01082dc..1b572cc 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -68,6 +68,7 @@ class MetaBaseWrapper { std::optional dumped_keys; if (dumped_meta) { + auto dumped_meta_str = from_unsigned_sv(*dumped_meta); oxenc::bt_dict_consumer combined{dumped_meta_str}; @@ -101,7 +102,8 @@ class MetaBaseWrapper { *info, *members); - return std::make_unique(info, members, keys,group_ed25519_pubkey, group_ed25519_secretkey); + return std::make_unique( + info, members, keys, group_ed25519_pubkey, group_ed25519_secretkey); }); } }; diff --git a/src/utilities.hpp b/src/utilities.hpp index 8a99ef7..45ebbe3 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -8,7 +8,6 @@ #include #include #include -#include #include "session/config/namespaces.hpp" #include "session/types.hpp" From 52bd57f0fc5615d6d43dd17ebe27121b1c105306 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 9 Jul 2024 16:37:14 +1000 Subject: [PATCH 50/64] fix: do not get_or_construct except when excplicitely being called --- src/groups/meta_group_wrapper.cpp | 94 +++++++++++++++---------------- src/groups/meta_group_wrapper.hpp | 14 ++--- types/groups/groupmembers.d.ts | 14 ++--- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 925e0c9..80b5158 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -417,84 +417,83 @@ Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& inf }); } -Napi::Value MetaGroupWrapper::memberSetName(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { +void MetaGroupWrapper::memberSetName(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { assertIsString(info[0]); assertIsString(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto newName = toCppString(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_name(newName); - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_name(newName); + this->meta_group->members->set(*m); + } }); } -Napi::Value MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { +void MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { assertIsString(info[0]); assertIsBoolean(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_invited(failed); - this->meta_group->members->set(m); - - return this->meta_group->members->get_or_construct(pubkeyHex); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_invited(failed); + this->meta_group->members->set(*m); + } }); } -Napi::Value MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { +void MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_accepted(); - - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_accepted(); + this->meta_group->members->set(*m); + } }); } -Napi::Value MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { - - return wrapResult(info, [&] { +void MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { assertInfoLength(info, 2); assertIsString(info[0]); assertIsBoolean(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.set_promoted(failed); - - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_promoted(failed); + this->meta_group->members->set(*m); + } }); } -Napi::Value MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { +void MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { + wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); // Note: this step might add an admin which was removed back once he accepts the promotion, // but there is not much we can do about it - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.admin = true; + auto m = this->meta_group->members->get(pubkeyHex); + m->admin = true; - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + this->meta_group->members->set(*m); }); } -Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { +void MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { + wrapExceptions(info, [&] { assertInfoLength(info, 2); assertIsString(info[0]); assertIsObject(info[1]); @@ -502,15 +501,16 @@ Napi::Value MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto profilePicture = profile_pic_from_object(info[1]); - auto m = this->meta_group->members->get_or_construct(pubkeyHex); - m.profile_picture = profilePicture; - this->meta_group->members->set(m); - return this->meta_group->members->get_or_construct(m.session_id); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->profile_picture = profilePicture; + this->meta_group->members->set(*m); + } }); } -Napi::Value MetaGroupWrapper::membersMarkPendingRemoval(const Napi::CallbackInfo& info) { - return wrapResult(info, [&] { +void MetaGroupWrapper::membersMarkPendingRemoval(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { assertInfoLength(info, 2); auto toUpdateJSValue = info[0]; auto withMessageJSValue = info[1]; @@ -522,12 +522,12 @@ Napi::Value MetaGroupWrapper::membersMarkPendingRemoval(const Napi::CallbackInfo auto toUpdateJS = toUpdateJSValue.As(); for (uint32_t i = 0; i < toUpdateJS.Length(); i++) { auto pubkeyHex = toCppString(toUpdateJS[i], __PRETTY_FUNCTION__); - auto existing = this->meta_group->members->get_or_construct(pubkeyHex); - existing.set_removed(withMessages); - this->meta_group->members->set(existing); + auto existing = this->meta_group->members->get(pubkeyHex); + if (existing) { + existing->set_removed(withMessages); + this->meta_group->members->set(*existing); + } } - - return true; }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 25336e2..c4a5d93 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -73,14 +73,14 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberGetAllPendingRemovals(const Napi::CallbackInfo& info); Napi::Value memberGet(const Napi::CallbackInfo& info); Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); - Napi::Value memberSetName(const Napi::CallbackInfo& info); - Napi::Value memberSetInvited(const Napi::CallbackInfo& info); - Napi::Value memberSetAccepted(const Napi::CallbackInfo& info); - Napi::Value memberSetPromoted(const Napi::CallbackInfo& info); - Napi::Value memberSetAdmin(const Napi::CallbackInfo& info); - Napi::Value memberSetProfilePicture(const Napi::CallbackInfo& info); + void memberSetName(const Napi::CallbackInfo& info); + void memberSetInvited(const Napi::CallbackInfo& info); + void memberSetAccepted(const Napi::CallbackInfo& info); + void memberSetPromoted(const Napi::CallbackInfo& info); + void memberSetAdmin(const Napi::CallbackInfo& info); + void memberSetProfilePicture(const Napi::CallbackInfo& info); Napi::Value memberEraseAndRekey(const Napi::CallbackInfo& info); - Napi::Value membersMarkPendingRemoval(const Napi::CallbackInfo& info); + void membersMarkPendingRemoval(const Napi::CallbackInfo& info); /** Keys Actions */ diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 8adb848..8461f9a 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -35,16 +35,16 @@ declare module 'libsession_util_nodejs' { memberGetAllPendingRemovals: () => Array; // setters - memberSetName: (pubkeyHex: PubkeyType, newName: string) => GroupMemberGet; - memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; - memberSetPromoted: (pubkeyHex: PubkeyType, failed: boolean) => GroupMemberGet; - memberSetAdmin: (pubkeyHex: PubkeyType) => GroupMemberGet; - memberSetAccepted: (pubkeyHex: PubkeyType) => GroupMemberGet; + memberSetName: (pubkeyHex: PubkeyType, newName: string) => void; + memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => void; + memberSetPromoted: (pubkeyHex: PubkeyType, failed: boolean) => void; + memberSetAdmin: (pubkeyHex: PubkeyType) => void; + memberSetAccepted: (pubkeyHex: PubkeyType) => void; memberSetProfilePicture: ( pubkeyHex: PubkeyType, profilePicture: ProfilePicture - ) => GroupMemberGet; - membersMarkPendingRemoval: (members: Array, withMessages: boolean) => boolean; + ) => void; + membersMarkPendingRemoval: (members: Array, withMessages: boolean) => void; // eraser memberEraseAndRekey: (members: Array) => boolean; From 760fffce80f466854dc97b0e5f9ebbf6c698d931 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 24 Jul 2024 14:50:07 +1000 Subject: [PATCH 51/64] feat: add keysAdmin and memberConstruct&Set --- package.json | 3 ++- src/groups/meta_group_wrapper.cpp | 30 ++++++++++++++++++++++++++---- src/groups/meta_group_wrapper.hpp | 3 +++ types/groups/groupkeys.d.ts | 1 + types/groups/groupmembers.d.ts | 2 ++ types/groups/metagroup.d.ts | 4 ++++ 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ba0c0f7..b7efa2a 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,6 @@ "cmake-js": "7.2.1", "node-addon-api": "^6.1.0" }, - "typings": "index.d.ts" + "typings": "index.d.ts", + "packageManager": "yarn@1.22.19" } diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 80b5158..19eb039 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -37,6 +37,9 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { // members exposed functions InstanceMethod("memberGet", &MetaGroupWrapper::memberGet), InstanceMethod("memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), + InstanceMethod( + "memberConstructAndSet", &MetaGroupWrapper::memberConstructAndSet), + InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), InstanceMethod( "memberGetAllPendingRemovals", @@ -417,6 +420,17 @@ Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& inf }); } +void MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto created = meta_group->members->get_or_construct(pubkeyHex); + meta_group->members->set(created); + }); +} + void MetaGroupWrapper::memberSetName(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertIsString(info[0]); @@ -477,7 +491,6 @@ void MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { } void MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { - wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); @@ -485,9 +498,10 @@ void MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { // Note: this step might add an admin which was removed back once he accepts the promotion, // but there is not much we can do about it auto m = this->meta_group->members->get(pubkeyHex); - m->admin = true; - - this->meta_group->members->set(*m); + if (m) { + m->admin = true; + this->meta_group->members->set(*m); + } }); } @@ -689,6 +703,14 @@ Napi::Value MetaGroupWrapper::loadAdminKeys(const Napi::CallbackInfo& info) { }); } + +Napi::Value MetaGroupWrapper::keysAdmin(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + assertInfoLength(info, 0); + return this->meta_group->keys->admin(); + }); +} + Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index c4a5d93..dc160df 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -73,6 +73,8 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberGetAllPendingRemovals(const Napi::CallbackInfo& info); Napi::Value memberGet(const Napi::CallbackInfo& info); Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); + void memberConstructAndSet(const Napi::CallbackInfo& info); + void memberSetName(const Napi::CallbackInfo& info); void memberSetInvited(const Napi::CallbackInfo& info); void memberSetAccepted(const Napi::CallbackInfo& info); @@ -98,6 +100,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value swarmSubaccountSign(const Napi::CallbackInfo& info); Napi::Value swarmVerifySubAccount(const Napi::CallbackInfo& info); Napi::Value loadAdminKeys(const Napi::CallbackInfo& info); + Napi::Value keysAdmin(const Napi::CallbackInfo& info); }; } // namespace session::nodeapi diff --git a/types/groups/groupkeys.d.ts b/types/groups/groupkeys.d.ts index 3865f67..41d92e1 100644 --- a/types/groups/groupkeys.d.ts +++ b/types/groups/groupkeys.d.ts @@ -7,6 +7,7 @@ declare module 'libsession_util_nodejs' { keyRekey: () => Uint8Array; keyGetAll: () => Array; loadKeyMessage: (hash: string, data: Uint8Array, timestampMs: number) => boolean; + keysAdmin: () => boolean; keyGetCurrentGen: () => number; currentHashes: () => Array; diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 8461f9a..40918ea 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -31,6 +31,8 @@ declare module 'libsession_util_nodejs' { // GroupMember related methods memberGet: (pubkeyHex: PubkeyType) => GroupMemberGet | null; memberGetOrConstruct: (pubkeyHex: PubkeyType) => GroupMemberGet; + memberConstructAndSet: (pubkeyHex: PubkeyType) => void; + memberGetAll: () => Array; memberGetAllPendingRemovals: () => Array; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 24182fd..a8abadf 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -76,6 +76,7 @@ declare module 'libsession_util_nodejs' { // members public memberGet: MetaGroupWrapper['memberGet']; public memberGetOrConstruct: MetaGroupWrapper['memberGetOrConstruct']; + public memberConstructAndSet: MetaGroupWrapper['memberConstructAndSet']; public memberGetAll: MetaGroupWrapper['memberGetAll']; public memberGetAllPendingRemovals: MetaGroupWrapper['memberGetAllPendingRemovals']; public memberSetAccepted: MetaGroupWrapper['memberSetAccepted']; @@ -92,6 +93,7 @@ declare module 'libsession_util_nodejs' { public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; public keyRekey: MetaGroupWrapper['keyRekey']; public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; + public keysAdmin: MetaGroupWrapper['keysAdmin']; public keyGetCurrentGen: MetaGroupWrapper['keyGetCurrentGen']; public encryptMessages: MetaGroupWrapper['encryptMessages']; public decryptMessage: MetaGroupWrapper['decryptMessage']; @@ -119,6 +121,7 @@ declare module 'libsession_util_nodejs' { // member actions | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall @@ -135,6 +138,7 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall From 04cf81ef6a5baaa073b5a478584a09e45a096f5f Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 7 Aug 2024 13:38:32 +1000 Subject: [PATCH 52/64] feat: move back from libquic branch, for now --- libsession-util | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsession-util b/libsession-util index cffdbde..790b0fd 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit cffdbde7061b935397c69ab816910228ddf5cb12 +Subproject commit 790b0fd8ea1ef43357e544ae585d79d682d3726b From 81e191c283b7d2b976edcefb8d2f48d61fdd8b62 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 7 Aug 2024 15:33:44 +1000 Subject: [PATCH 53/64] feat: break down set promotion&invite setters --- src/groups/meta_group_wrapper.cpp | 54 ++++++++++++++++++++++++------- src/groups/meta_group_wrapper.hpp | 20 +++++++++--- types/groups/groupmembers.d.ts | 47 +++++++++++++++++++-------- types/groups/metagroup.d.ts | 16 +++++---- 4 files changed, 101 insertions(+), 36 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 19eb039..b362d3f 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -47,11 +47,19 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod( "membersMarkPendingRemoval", &MetaGroupWrapper::membersMarkPendingRemoval), - InstanceMethod("memberSetName", &MetaGroupWrapper::memberSetName), + InstanceMethod( + "memberSetNameTruncated", &MetaGroupWrapper::memberSetNameTruncated), InstanceMethod("memberSetInvited", &MetaGroupWrapper::memberSetInvited), InstanceMethod("memberSetAccepted", &MetaGroupWrapper::memberSetAccepted), InstanceMethod("memberSetPromoted", &MetaGroupWrapper::memberSetPromoted), - InstanceMethod("memberSetAdmin", &MetaGroupWrapper::memberSetAdmin), + InstanceMethod( + "memberSetPromotionSent", &MetaGroupWrapper::memberSetPromotionSent), + InstanceMethod( + "memberSetPromotionFailed", + &MetaGroupWrapper::memberSetPromotionFailed), + InstanceMethod( + "memberSetPromotionAccepted", + &MetaGroupWrapper::memberSetPromotionAccepted), InstanceMethod( "memberSetProfilePicture", &MetaGroupWrapper::memberSetProfilePicture), InstanceMethod("memberEraseAndRekey", &MetaGroupWrapper::memberEraseAndRekey), @@ -73,6 +81,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod( "swarmVerifySubAccount", &MetaGroupWrapper::swarmVerifySubAccount), InstanceMethod("loadAdminKeys", &MetaGroupWrapper::loadAdminKeys), + InstanceMethod("keysAdmin", &MetaGroupWrapper::keysAdmin), InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), InstanceMethod( @@ -431,7 +440,7 @@ void MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& info) { }); } -void MetaGroupWrapper::memberSetName(const Napi::CallbackInfo& info) { +void MetaGroupWrapper::memberSetNameTruncated(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertIsString(info[0]); assertIsString(info[1]); @@ -477,29 +486,51 @@ void MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) { void MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { - assertInfoLength(info, 2); + assertInfoLength(info, 1); assertIsString(info[0]); - assertIsBoolean(info[1]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); auto m = this->meta_group->members->get(pubkeyHex); if (m) { - m->set_promoted(failed); + m->set_promoted(); this->meta_group->members->set(*m); } }); } -void MetaGroupWrapper::memberSetAdmin(const Napi::CallbackInfo& info) { +void MetaGroupWrapper::memberSetPromotionSent(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - // Note: this step might add an admin which was removed back once he accepts the promotion, - // but there is not much we can do about it auto m = this->meta_group->members->get(pubkeyHex); if (m) { - m->admin = true; + m->set_promotion_sent(); + this->meta_group->members->set(*m); + } + }); +} + +void MetaGroupWrapper::memberSetPromotionFailed(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_promotion_failed(); + this->meta_group->members->set(*m); + } + }); +} + +void MetaGroupWrapper::memberSetPromotionAccepted(const Napi::CallbackInfo& info) { + wrapExceptions(info, [&] { + assertInfoLength(info, 1); + assertIsString(info[0]); + auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto m = this->meta_group->members->get(pubkeyHex); + if (m) { + m->set_promotion_accepted(); this->meta_group->members->set(*m); } }); @@ -703,7 +734,6 @@ Napi::Value MetaGroupWrapper::loadAdminKeys(const Napi::CallbackInfo& info) { }); } - Napi::Value MetaGroupWrapper::keysAdmin(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 0); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index dc160df..4a10116 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -21,13 +21,23 @@ struct toJs_impl { obj["pubkeyHex"] = toJs(env, info.session_id); obj["name"] = toJs(env, info.name); obj["profilePicture"] = toJs(env, info.profile_picture); + obj["removedStatus"] = toJs(env, info.removed_status); + + // invites + obj["inviteNotSent"] = toJs(env, info.invite_not_sent()); obj["invitePending"] = toJs(env, info.invite_pending()); + obj["inviteAccepted"] = toJs(env, info.invite_status == 0); obj["inviteFailed"] = toJs(env, info.invite_failed()); + + // promotions + obj["promotionNotSent"] = toJs(env, info.promotion_not_sent()); obj["promotionPending"] = toJs(env, info.promotion_pending()); obj["promotionFailed"] = toJs(env, info.promotion_failed()); obj["promoted"] = toJs(env, info.promoted()); - obj["admin"] = toJs(env, info.admin); - obj["removedStatus"] = toJs(env, info.removed_status); + + // removed status + obj["isRemoved"] = toJs(env, info.is_removed()); + obj["shouldRemoveMessages"] = toJs(env, info.should_remove_messages()); return obj; } @@ -75,11 +85,13 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); void memberConstructAndSet(const Napi::CallbackInfo& info); - void memberSetName(const Napi::CallbackInfo& info); + void memberSetNameTruncated(const Napi::CallbackInfo& info); void memberSetInvited(const Napi::CallbackInfo& info); void memberSetAccepted(const Napi::CallbackInfo& info); void memberSetPromoted(const Napi::CallbackInfo& info); - void memberSetAdmin(const Napi::CallbackInfo& info); + void memberSetPromotionSent(const Napi::CallbackInfo& info); + void memberSetPromotionFailed(const Napi::CallbackInfo& info); + void memberSetPromotionAccepted(const Napi::CallbackInfo& info); void memberSetProfilePicture(const Napi::CallbackInfo& info); Napi::Value memberEraseAndRekey(const Napi::CallbackInfo& info); void membersMarkPendingRemoval(const Napi::CallbackInfo& info); diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 40918ea..a6b88d9 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -13,18 +13,29 @@ declare module 'libsession_util_nodejs' { }; export type GroupMemberGet = GroupMemberShared & { + /** Default state, before we try sending the invite */ + inviteNotSent: boolean; + /** We did send the invite to the user */ invitePending: boolean; + /** The invite was accepted by the user */ + inviteAccepted: boolean; + + /** We failed to send the invite to the user */ inviteFailed: boolean; + + /** Default state, before we try sending the promotion */ + promotionNotSent: boolean; + /** We did send the promotion, not accepted yet */ promotionPending: boolean; + /** We tried to send the promotion but failed */ promotionFailed: boolean; - /** - * - 0 means not removed, - * - 1 means removed (libsession: REMOVED_MEMBER), - * - 2 means removed with messages (libsession: REMOVED_MEMBER_AND_MESSAGES) - */ - removedStatus: number; + /** The user is already an admin *or* has a pending promotion */ promoted: boolean; - admin: boolean; + + /** True if the user should be removed from the group */ + isRemoved: boolean; + /** True if the user and his messages should be removed from the group */ + shouldRemoveMessages: boolean; }; type GroupMemberWrapper = { @@ -37,15 +48,23 @@ declare module 'libsession_util_nodejs' { memberGetAllPendingRemovals: () => Array; // setters - memberSetName: (pubkeyHex: PubkeyType, newName: string) => void; + memberSetNameTruncated: (pubkeyHex: PubkeyType, newName: string) => void; + + /** A member invite states defaults to invite-not-sent. Use this function to mark that you've sent one, or at least tried (failed: boolean)*/ memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => void; - memberSetPromoted: (pubkeyHex: PubkeyType, failed: boolean) => void; - memberSetAdmin: (pubkeyHex: PubkeyType) => void; + /** User has accepted an invitation and is now a regular member of the group */ memberSetAccepted: (pubkeyHex: PubkeyType) => void; - memberSetProfilePicture: ( - pubkeyHex: PubkeyType, - profilePicture: ProfilePicture - ) => void; + + /** Mark the member as waiting a promotion to be sent to them */ + memberSetPromoted: (pubkeyHex: PubkeyType) => void; + /** Called when we did send the promotion to the member */ + memberSetPromotionSent: (pubkeyHex: PubkeyType) => void; + /** Called when we did send the promotion to the member, but failed */ + memberSetPromotionFailed: (pubkeyHex: PubkeyType) => void; + /** Called when the member accepted the promotion */ + memberSetPromotionAccepted: (pubkeyHex: PubkeyType) => void; + + memberSetProfilePicture: (pubkeyHex: PubkeyType, profilePicture: ProfilePicture) => void; membersMarkPendingRemoval: (members: Array, withMessages: boolean) => void; // eraser diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index a8abadf..4e4cea7 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -17,8 +17,8 @@ declare module 'libsession_util_nodejs' { GroupMemberWrapper & GroupKeysWrapper & { // shared actions - init: (options: GroupWrapperConstructor) => void; - free: () => void; + init: (options: GroupWrapperConstructor) => void; + free: () => void; needsPush: () => boolean; push: () => { groupInfo: PushConfigResult | null; @@ -80,9 +80,11 @@ declare module 'libsession_util_nodejs' { public memberGetAll: MetaGroupWrapper['memberGetAll']; public memberGetAllPendingRemovals: MetaGroupWrapper['memberGetAllPendingRemovals']; public memberSetAccepted: MetaGroupWrapper['memberSetAccepted']; - public memberSetName: MetaGroupWrapper['memberSetName']; + public memberSetNameTruncated: MetaGroupWrapper['memberSetNameTruncated']; public memberSetPromoted: MetaGroupWrapper['memberSetPromoted']; - public memberSetAdmin: MetaGroupWrapper['memberSetAdmin']; + public memberSetPromotionAccepted: MetaGroupWrapper['memberSetPromotionAccepted']; + public memberSetPromotionSent: MetaGroupWrapper['memberSetPromotionSent']; + public memberSetPromotionFailed: MetaGroupWrapper['memberSetPromotionFailed']; public memberSetInvited: MetaGroupWrapper['memberSetInvited']; public memberEraseAndRekey: MetaGroupWrapper['memberEraseAndRekey']; public membersMarkPendingRemoval: MetaGroupWrapper['membersMarkPendingRemoval']; @@ -125,9 +127,11 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall | MakeActionCall - | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall | MakeActionCall | MakeActionCall | MakeActionCall From adbb3ce972d2961d5009221db9074a5a246cdef7 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 29 Oct 2024 15:38:12 +1100 Subject: [PATCH 54/64] chore: pull latest libsession-util and fix typo --- libsession-util | 2 +- types/multi_encrypt/multi_encrypt.d.ts | 2 +- types/shared.d.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsession-util b/libsession-util index 790b0fd..e2d35df 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 790b0fd8ea1ef43357e544ae585d79d682d3726b +Subproject commit e2d35df70058fd39d8a13f6384ea1c1eacb3ee93 diff --git a/types/multi_encrypt/multi_encrypt.d.ts b/types/multi_encrypt/multi_encrypt.d.ts index 175fb02..499075d 100644 --- a/types/multi_encrypt/multi_encrypt.d.ts +++ b/types/multi_encrypt/multi_encrypt.d.ts @@ -25,7 +25,7 @@ declare module 'libsession_util_nodejs' { export type MultiEncryptActionsCalls = MakeWrapperActionCalls; /** - * To be used inside the web worker only (calls are synchronous and won't work asynchrously) + * To be used inside the web worker only (calls are synchronous and won't work asynchronously) */ export class MultiEncryptWrapperNode { public static multiEncrypt: MultiEncryptWrapper['multiEncrypt']; diff --git a/types/shared.d.ts b/types/shared.d.ts index 5260a66..863755a 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -100,7 +100,7 @@ declare module 'libsession_util_nodejs' { type MakeGroupActionCall = [ B, ...Parameters - ]; // all of the groupActionCalls need the pubkey of the group we are targetting + ]; // all of the groupActionCalls need the pubkey of the group we are targeting type AsyncGroupWrapper any> = ( groupPk: GroupPubkeyType, @@ -140,7 +140,7 @@ declare module 'libsession_util_nodejs' { export type Uint8ArrayLen64 = Uint8Array; export type Uint8ArrayLen32 = Uint8Array; export type Uint8ArrayLen36 = Uint8Array; // subaccount tokens are 36 bytes long - export type Uint8ArrayLen100 = Uint8Array; // subaccount authdata are 100 bytes long + export type Uint8ArrayLen100 = Uint8Array; // subaccount auth data are 100 bytes long export type EncryptionDomain = 'SessionGroupKickedMessage'; From 6820f4ac78cc9d79fae17a5068483754efc70939 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 12 Nov 2024 15:39:49 +1100 Subject: [PATCH 55/64] feat: memberStatus instead of a bunch of bools for libsession state --- src/groups/meta_group_wrapper.hpp | 33 +++++++++++++------- src/user_groups_config.cpp | 50 ++++++++++++++++++++++++++----- src/user_groups_config.hpp | 3 ++ types/groups/groupmembers.d.ts | 39 ++++++++++++------------ types/user/usergroups.d.ts | 18 ++++++++--- 5 files changed, 102 insertions(+), 41 deletions(-) diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 4a10116..829124c 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -23,17 +23,28 @@ struct toJs_impl { obj["profilePicture"] = toJs(env, info.profile_picture); obj["removedStatus"] = toJs(env, info.removed_status); - // invites - obj["inviteNotSent"] = toJs(env, info.invite_not_sent()); - obj["invitePending"] = toJs(env, info.invite_pending()); - obj["inviteAccepted"] = toJs(env, info.invite_status == 0); - obj["inviteFailed"] = toJs(env, info.invite_failed()); - - // promotions - obj["promotionNotSent"] = toJs(env, info.promotion_not_sent()); - obj["promotionPending"] = toJs(env, info.promotion_pending()); - obj["promotionFailed"] = toJs(env, info.promotion_failed()); - obj["promoted"] = toJs(env, info.promoted()); + // promoted() is true as soon as the member is scheduled to be promoted + // Note: this should be part of `libsession-util`, not `libsession-util-nodejs` + if (info.promoted() && !info.promotion_pending()) { + obj["memberStatus"] = toJs(env, "PROMOTION_ACCEPTED"); + } else if (info.promotion_pending()) { + obj["memberStatus"] = toJs(env, "PROMOTION_SENT"); + } else if (info.promotion_failed()) { + obj["memberStatus"] = toJs(env, "PROMOTION_FAILED"); + } else if (info.admin) { + obj["memberStatus"] = toJs(env, "PROMOTION_NOT_SENT"); + } else if (info.invite_status == 0) { + obj["memberStatus"] = toJs(env, "INVITE_ACCEPTED"); + } else if (info.invite_pending()) { + obj["memberStatus"] = toJs(env, "INVITE_SENT"); + } else if (info.invite_failed()) { + obj["memberStatus"] = toJs(env, "INVITE_FAILED"); + } else { + // this is probably a bad idea to have a catch-all else, but we have to when we consider + // upgrades of libsession-util + obj["memberStatus"] = toJs(env, "INVITE_NOT_SENT"); + } + obj["nominatedAdmin"] = toJs(env, info.admin); // removed status obj["isRemoved"] = toJs(env, info.is_removed()); diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 9917e28..1b29ffc 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -70,6 +70,7 @@ struct toJs_impl { obj["authData"] = toJs(env, info.auth_data); obj["invitePending"] = toJs(env, info.invited); obj["kicked"] = toJs(env, info.kicked()); + obj["destroyed"] = toJs(env, info.isDestroyed()); return obj; } @@ -103,6 +104,9 @@ void UserGroupsWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("getGroup", &UserGroupsWrapper::getGroup), InstanceMethod("getAllGroups", &UserGroupsWrapper::getAllGroups), InstanceMethod("setGroup", &UserGroupsWrapper::setGroup), + InstanceMethod("markGroupKicked", &UserGroupsWrapper::markGroupKicked), + InstanceMethod("markGroupInvited", &UserGroupsWrapper::markGroupInvited), + InstanceMethod("markGroupDestroyed", &UserGroupsWrapper::markGroupDestroyed), InstanceMethod("eraseGroup", &UserGroupsWrapper::eraseGroup), }); @@ -316,13 +320,6 @@ Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { group_info.invited = *invited; } - if (auto kicked = - maybeNonemptyBoolean(obj.Get("kicked"), "UserGroupsWrapper::setGroup kicked")) { - if (*kicked) { - group_info.setKicked(); - } - } - if (auto secretKey = maybeNonemptyBuffer( obj.Get("secretKey"), "UserGroupsWrapper::setGroup secretKey")) { group_info.secretkey = *secretKey; @@ -343,6 +340,45 @@ Napi::Value UserGroupsWrapper::setGroup(const Napi::CallbackInfo& info) { }); } +Napi::Value UserGroupsWrapper::markGroupKicked(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto groupPk = getStringArgs<1>(info); + + auto group = config.get_group(groupPk); + if (group) { + group->markKicked(); + config.set(*group); + } + return config.get_or_construct_group(groupPk); + }); +} + +Napi::Value UserGroupsWrapper::markGroupInvited(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto groupPk = getStringArgs<1>(info); + + auto group = config.get_group(groupPk); + if (group) { + group->markInvited(); + config.set(*group); + } + return config.get_or_construct_group(groupPk); + }); +} + +Napi::Value UserGroupsWrapper::markGroupDestroyed(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + auto groupPk = getStringArgs<1>(info); + + auto group = config.get_group(groupPk); + if (group) { + group->markDestroyed(); + config.set(*group); + } + return config.get_or_construct_group(groupPk); + }); +} + Napi::Value UserGroupsWrapper::eraseGroup(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { return config.erase_group(getStringArgs<1>(info)); }); } diff --git a/src/user_groups_config.hpp b/src/user_groups_config.hpp index 7134491..be8bcf1 100644 --- a/src/user_groups_config.hpp +++ b/src/user_groups_config.hpp @@ -34,6 +34,9 @@ class UserGroupsWrapper : public ConfigBaseImpl, public Napi::ObjectWrap & - AllFieldsNullable>; + AllFieldsNullable>; type UserGroupsWrapper = BaseConfigWrapper & { init: (secretKey: Uint8Array, dump: Uint8Array | null) => void; @@ -90,6 +91,9 @@ declare module 'libsession_util_nodejs' { getGroup: (pubkeyHex: GroupPubkeyType) => UserGroupsGet | null; getAllGroups: () => Array; setGroup: (info: UserGroupsSet) => UserGroupsGet; + markGroupKicked: (pubkeyHex: GroupPubkeyType) => UserGroupsGet; + markGroupInvited: (pubkeyHex: GroupPubkeyType) => UserGroupsGet; + markGroupDestroyed: (pubkeyHex: GroupPubkeyType) => UserGroupsGet; eraseGroup: (pubkeyHex: GroupPubkeyType) => boolean; }; @@ -115,6 +119,9 @@ declare module 'libsession_util_nodejs' { public getGroup: UserGroupsWrapper['getGroup']; public getAllGroups: UserGroupsWrapper['getAllGroups']; public setGroup: UserGroupsWrapper['setGroup']; + public markGroupKicked: UserGroupsWrapper['markGroupKicked']; + public markGroupInvited: UserGroupsWrapper['markGroupInvited']; + public markGroupDestroyed: UserGroupsWrapper['markGroupDestroyed']; public eraseGroup: UserGroupsWrapper['eraseGroup']; } @@ -134,5 +141,8 @@ declare module 'libsession_util_nodejs' { | MakeActionCall | MakeActionCall | MakeActionCall + | MakeActionCall + | MakeActionCall + | MakeActionCall | MakeActionCall; } From 3134efa0ab86a3fe0b80dc9e3f05a6ed26033216 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 13 Nov 2024 09:53:34 +1100 Subject: [PATCH 56/64] chore: fetch latest libsession-util dev --- libsession-util | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsession-util b/libsession-util index e2d35df..278183d 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit e2d35df70058fd39d8a13f6384ea1c1eacb3ee93 +Subproject commit 278183dce698c65af2d6215d2cf3ed1405a1589d From d421a736008a43af432cd22a5719ea9d50dded76 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 13 Nov 2024 15:12:56 +1100 Subject: [PATCH 57/64] chore: change submodule of libsession-util to foundation's --- .gitmodules | 2 +- README.md | 6 +++--- libsession-util | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8720b3c..d6ca3b1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "libsession-util"] path = libsession-util - url = https://github.com/oxen-io/libsession-util.git + url = https://github.com/session-foundation/libsession-util.git diff --git a/README.md b/README.md index d57b09f..e45c109 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Clone this project to somewhere **not** part of `session-desktop` node_modules: ``` cd [FOLDER_NOT_IN_SESSION_DESKTOP] -git clone --recursive git@github.com:oxen-io/libsession-util-nodejs.git +git clone --recursive git@github.com:session-foundation/libsession-util-nodejs.git ``` Always do your changes in `[FOLDER_NOT_IN_SESSION_DESKTOP]/libsession-util-nodejs`, never in the one under session-desktop's `node_modules` as you might override your local changes. @@ -31,7 +31,7 @@ Replace `[SESSION_DESKTOP_PATH]` with the full path to your `session-desktop` fo Every part of this command is needed and might need to be updated using your paths. Also, the `worker:libsession` needs to be recompiled too to include the just created .node file in itself. This is done by the `yarn build:workers` command. -Note: The `electron` property in the `config` object will need to be updated in the `package.json` every time we update `electron` package in [session-desktop](https://github.com/oxen-io/session-desktop/) so that the versions match. It is a node version, but not part of the official node docs. If you compiled the node module for an incorrect electron/node version you will get an error on `session-desktop` start. +Note: The `electron` property in the `config` object will need to be updated in the `package.json` every time we update `electron` package in [session-desktop](https://github.com/session-foundation/session-desktop/) so that the versions match. It is a node version, but not part of the official node docs. If you compiled the node module for an incorrect electron/node version you will get an error on `session-desktop` start. ### Making a Release and updating Session-desktop @@ -71,7 +71,7 @@ Once this is done, update the dependency on `session-desktop`. Make sure to remove the existing one first (with the include `yarn remove` below) as you might have messed up your `node_modules` doing the dev instructions. ``` -yarn remove libsession_util_nodejs && yarn add https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.1.15/libsession_util_nodejs-v0.1.15.tar.gz +yarn remove libsession_util_nodejs && yarn add https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.1.15/libsession_util_nodejs-v0.1.15.tar.gz ``` Keep in mind that you need to update the two version numbers (e.g. `0.1.15`) to the just created release version of this project. diff --git a/libsession-util b/libsession-util index 278183d..3a28cb7 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 278183dce698c65af2d6215d2cf3ed1405a1589d +Subproject commit 3a28cb74287b7c54e358cb3a1c6e1f03557eca33 From f72a9702e375a99d6e8af13044c301138ce809b3 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 18 Nov 2024 09:43:59 +1100 Subject: [PATCH 58/64] chore: move to session-foundation --- libsession-util | 2 +- types/groups/groupmembers.d.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libsession-util b/libsession-util index 3a28cb7..c29c934 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 3a28cb74287b7c54e358cb3a1c6e1f03557eca33 +Subproject commit c29c93457eb6abfdb9e13af378cc67a2dc68115d diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index ffa55b1..ee1f931 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -24,6 +24,13 @@ declare module 'libsession_util_nodejs' { export type GroupMemberGet = GroupMemberShared & { memberStatus: MemberStateGroupV2; + + /** + * NOT_REMOVED = 0: + * REMOVED_MEMBER = 1, + * REMOVED_MEMBER_AND_MESSAGES = 2; + */ + removedStatus: number; /** * True if the member is scheduled to get the keys (.admin field of libsession). * This is equivalent of memberStatus being one of: From c2793b58792b384fa9037f852495d52a4bacd969 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 18 Nov 2024 09:46:46 +1100 Subject: [PATCH 59/64] fix: memberStatus priority custom enum was incorrect --- src/groups/meta_group_wrapper.cpp | 5 +++-- src/groups/meta_group_wrapper.hpp | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index b362d3f..8bc7987 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -429,14 +429,15 @@ Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& inf }); } -void MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& info) { - wrapExceptions(info, [&] { +Napi::Value MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); auto created = meta_group->members->get_or_construct(pubkeyHex); meta_group->members->set(created); + return created; }); } diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 829124c..25f861a 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -35,15 +35,17 @@ struct toJs_impl { obj["memberStatus"] = toJs(env, "PROMOTION_NOT_SENT"); } else if (info.invite_status == 0) { obj["memberStatus"] = toJs(env, "INVITE_ACCEPTED"); - } else if (info.invite_pending()) { - obj["memberStatus"] = toJs(env, "INVITE_SENT"); + } else if (info.invite_not_sent()) { + obj["memberStatus"] = toJs(env, "INVITE_NOT_SENT"); } else if (info.invite_failed()) { obj["memberStatus"] = toJs(env, "INVITE_FAILED"); } else { - // this is probably a bad idea to have a catch-all else, but we have to when we consider - // upgrades of libsession-util - obj["memberStatus"] = toJs(env, "INVITE_NOT_SENT"); + // Note: INVITE_NOT_SENT is 3, which makes invite_pending() return true, so be sure to + // check for invite_not_sent() above. this is probably a bad idea to have a catch-all + // else, but we have to when we consider upgrades of libsession-util + obj["memberStatus"] = toJs(env, "INVITE_SENT"); } + obj["nominatedAdmin"] = toJs(env, info.admin); // removed status @@ -94,7 +96,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap { Napi::Value memberGetAllPendingRemovals(const Napi::CallbackInfo& info); Napi::Value memberGet(const Napi::CallbackInfo& info); Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info); - void memberConstructAndSet(const Napi::CallbackInfo& info); + Napi::Value memberConstructAndSet(const Napi::CallbackInfo& info); void memberSetNameTruncated(const Napi::CallbackInfo& info); void memberSetInvited(const Napi::CallbackInfo& info); From 873c63bb33175bcf6efd115354dd2d7f813dc9a2 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 18 Nov 2024 10:08:39 +1100 Subject: [PATCH 60/64] fix: add enum for removedStatus too --- src/groups/meta_group_wrapper.hpp | 28 +++++++++++++++++++--------- types/groups/groupmembers.d.ts | 9 +++------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 25f861a..8dab396 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -7,9 +7,13 @@ #include "../utilities.hpp" #include "./meta_group.hpp" #include "oxenc/bt_producer.h" +#include "session/config/user_groups.hpp" namespace session::nodeapi { using config::groups::Members; +using session::config::GROUP_DESTROYED; +using session::config::KICKED_FROM_GROUP; +using session::config::NOT_REMOVED; using session::config::groups::member; using session::nodeapi::MetaGroup; @@ -27,10 +31,10 @@ struct toJs_impl { // Note: this should be part of `libsession-util`, not `libsession-util-nodejs` if (info.promoted() && !info.promotion_pending()) { obj["memberStatus"] = toJs(env, "PROMOTION_ACCEPTED"); - } else if (info.promotion_pending()) { - obj["memberStatus"] = toJs(env, "PROMOTION_SENT"); } else if (info.promotion_failed()) { obj["memberStatus"] = toJs(env, "PROMOTION_FAILED"); + } else if (info.promotion_pending()) { + obj["memberStatus"] = toJs(env, "PROMOTION_SENT"); } else if (info.admin) { obj["memberStatus"] = toJs(env, "PROMOTION_NOT_SENT"); } else if (info.invite_status == 0) { @@ -39,19 +43,25 @@ struct toJs_impl { obj["memberStatus"] = toJs(env, "INVITE_NOT_SENT"); } else if (info.invite_failed()) { obj["memberStatus"] = toJs(env, "INVITE_FAILED"); - } else { + } else if (info.invite_pending()) { // Note: INVITE_NOT_SENT is 3, which makes invite_pending() return true, so be sure to - // check for invite_not_sent() above. this is probably a bad idea to have a catch-all - // else, but we have to when we consider upgrades of libsession-util + // check for invite_not_sent() above. obj["memberStatus"] = toJs(env, "INVITE_SENT"); + } else { + obj["memberStatus"] = toJs(env, "UNKNOWN"); } obj["nominatedAdmin"] = toJs(env, info.admin); - // removed status - obj["isRemoved"] = toJs(env, info.is_removed()); - obj["shouldRemoveMessages"] = toJs(env, info.should_remove_messages()); - + if (!info.is_removed()) { + obj["removedStatus"] = toJs(env, "NOT_REMOVED"); + } else { + if (info.should_remove_messages()) { + obj["removedStatus"] = toJs(env, "REMOVED_MEMBER_AND_MESSAGES"); + } else { + obj["removedStatus"] = toJs(env, "REMOVED_MEMBER"); + } + } return obj; } }; diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index ee1f931..2f604a7 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -20,7 +20,8 @@ declare module 'libsession_util_nodejs' { | 'PROMOTION_NOT_SENT' // as soon as we've scheduled that guy to be an admin, but before we've tried sending the promotion message | 'PROMOTION_FAILED' | 'PROMOTION_SENT' - | 'PROMOTION_ACCEPTED'; // regular admin + | 'PROMOTION_ACCEPTED' // regular admin + | 'UNKNOWN'; export type GroupMemberGet = GroupMemberShared & { memberStatus: MemberStateGroupV2; @@ -30,7 +31,7 @@ declare module 'libsession_util_nodejs' { * REMOVED_MEMBER = 1, * REMOVED_MEMBER_AND_MESSAGES = 2; */ - removedStatus: number; + removedStatus: 'NOT_REMOVED' | 'REMOVED_MEMBER' | 'REMOVED_MEMBER_AND_MESSAGES' | 'UNKNOWN'; /** * True if the member is scheduled to get the keys (.admin field of libsession). * This is equivalent of memberStatus being one of: @@ -40,10 +41,6 @@ declare module 'libsession_util_nodejs' { * - PROMOTION_ACCEPTED */ nominatedAdmin: boolean; - /** True if the user should be removed from the group */ - isRemoved: boolean; - /** True if the user and his messages should be removed from the group */ - shouldRemoveMessages: boolean; }; type GroupMemberWrapper = { From d6c00f970dae74fe60b3c19008b0dfafe56efd25 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 18 Nov 2024 11:26:39 +1100 Subject: [PATCH 61/64] chore: bump to 0.4.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b495e1..9c3b46f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "main": "index.js", "name": "libsession_util_nodejs", "description": "Wrappers for the Session Util Library", - "version": "0.4.3", + "version": "0.4.4", "license": "GPL-3.0", "author": { "name": "Oxen Project", From 15151d763599fccadc93669a757f2194834b3caa Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 20 Nov 2024 10:35:19 +1100 Subject: [PATCH 62/64] chore: address PR reviews --- .github/workflows/test.yml | 5 +---- src/base_config.hpp | 13 ------------ src/blinding/blinding.hpp | 2 +- src/groups/meta_group_wrapper.cpp | 7 ------ src/groups/meta_group_wrapper.hpp | 1 - src/meta/meta_base_wrapper.hpp | 1 - src/multi_encrypt/multi_encrypt.hpp | 7 +++--- src/user_config.cpp | 1 - src/utilities.hpp | 1 - types/groups/groupmembers.d.ts | 2 +- types/groups/index.d.ts | 3 +-- types/groups/metagroup.d.ts | 19 ++++++++++++++--- types/shared.d.ts | 2 +- types/user/usergroups.d.ts | 33 +++++++++++++++++++++++------ 14 files changed, 51 insertions(+), 46 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f39a6d6..5556cd5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,8 +17,6 @@ jobs: strategy: fail-fast: false - - matrix: os: [windows-2022, macos-12, ubuntu-20.04] env: @@ -68,7 +66,6 @@ jobs: sed -i "s/target_compile_options(oxen-logging-warnings INTERFACE/#target_compile_options(oxen-logging-warnings INTERFACE/" libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt cat libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt - - name: build libsession-util-nodejs shell: bash - run: yarn install --frozen-lockfile + run: yarn install --frozen-lockfile diff --git a/src/base_config.hpp b/src/base_config.hpp index 5119cb2..d99250e 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -106,19 +106,6 @@ class ConfigBaseImpl { Napi::Env env = info.Env(); - // config->logger = [env, class_name](session::config::LogLevel, std::string_view x) { - // std::string toLog = - // "libsession-util:" + std::string(class_name) + ": " + std::string(x) + - // "\n"; - - // Napi::Function consoleLog = env.Global() - // .Get("console") - // .As() - // .Get("log") - // .As(); - // consoleLog.Call({Napi::String::New(env, toLog)}); - // }; - return config; }); } diff --git a/src/blinding/blinding.hpp b/src/blinding/blinding.hpp index 9f6c6d7..d244696 100644 --- a/src/blinding/blinding.hpp +++ b/src/blinding/blinding.hpp @@ -19,7 +19,7 @@ class BlindingWrapper : public Napi::ObjectWrap { public: BlindingWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap{info} { throw std::invalid_argument( - "BlindingWrapper is all static and don't need to be constructed"); + "BlindingWrapper is static and doesn't need to be constructed"); } static void Init(Napi::Env env, Napi::Object exports) { diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 8bc7987..38a4a11 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -20,7 +20,6 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { "MetaGroupWrapperNode", { // shared exposed functions - InstanceMethod("needsPush", &MetaGroupWrapper::needsPush), InstanceMethod("push", &MetaGroupWrapper::push), InstanceMethod("needsDump", &MetaGroupWrapper::needsDump), @@ -39,7 +38,6 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("memberGetOrConstruct", &MetaGroupWrapper::memberGetOrConstruct), InstanceMethod( "memberConstructAndSet", &MetaGroupWrapper::memberConstructAndSet), - InstanceMethod("memberGetAll", &MetaGroupWrapper::memberGetAll), InstanceMethod( "memberGetAllPendingRemovals", @@ -65,15 +63,12 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("memberEraseAndRekey", &MetaGroupWrapper::memberEraseAndRekey), // keys exposed functions - InstanceMethod("keysNeedsRekey", &MetaGroupWrapper::keysNeedsRekey), InstanceMethod("keyRekey", &MetaGroupWrapper::keyRekey), InstanceMethod("keyGetAll", &MetaGroupWrapper::keyGetAll), - InstanceMethod("currentHashes", &MetaGroupWrapper::currentHashes), InstanceMethod("loadKeyMessage", &MetaGroupWrapper::loadKeyMessage), InstanceMethod("keyGetCurrentGen", &MetaGroupWrapper::keyGetCurrentGen), - InstanceMethod("encryptMessages", &MetaGroupWrapper::encryptMessages), InstanceMethod("decryptMessage", &MetaGroupWrapper::decryptMessage), InstanceMethod("makeSwarmSubAccount", &MetaGroupWrapper::makeSwarmSubAccount), @@ -82,7 +77,6 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) { "swarmVerifySubAccount", &MetaGroupWrapper::swarmVerifySubAccount), InstanceMethod("loadAdminKeys", &MetaGroupWrapper::loadAdminKeys), InstanceMethod("keysAdmin", &MetaGroupWrapper::keysAdmin), - InstanceMethod("swarmSubaccountSign", &MetaGroupWrapper::swarmSubaccountSign), InstanceMethod( "generateSupplementKeys", &MetaGroupWrapper::generateSupplementKeys), @@ -538,7 +532,6 @@ void MetaGroupWrapper::memberSetPromotionAccepted(const Napi::CallbackInfo& info } void MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { - wrapExceptions(info, [&] { assertInfoLength(info, 2); assertIsString(info[0]); diff --git a/src/groups/meta_group_wrapper.hpp b/src/groups/meta_group_wrapper.hpp index 8dab396..2b2562c 100644 --- a/src/groups/meta_group_wrapper.hpp +++ b/src/groups/meta_group_wrapper.hpp @@ -120,7 +120,6 @@ class MetaGroupWrapper : public Napi::ObjectWrap { void membersMarkPendingRemoval(const Napi::CallbackInfo& info); /** Keys Actions */ - Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info); Napi::Value keyRekey(const Napi::CallbackInfo& info); Napi::Value keyGetAll(const Napi::CallbackInfo& info); diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 1b572cc..75e71e9 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -68,7 +68,6 @@ class MetaBaseWrapper { std::optional dumped_keys; if (dumped_meta) { - auto dumped_meta_str = from_unsigned_sv(*dumped_meta); oxenc::bt_dict_consumer combined{dumped_meta_str}; diff --git a/src/multi_encrypt/multi_encrypt.hpp b/src/multi_encrypt/multi_encrypt.hpp index b71c2eb..6816fda 100644 --- a/src/multi_encrypt/multi_encrypt.hpp +++ b/src/multi_encrypt/multi_encrypt.hpp @@ -4,20 +4,19 @@ #include +#include "../utilities.hpp" #include "session/config/user_profile.hpp" #include "session/multi_encrypt.hpp" #include "session/random.hpp" -#include "../utilities.hpp" namespace session::nodeapi { class MultiEncryptWrapper : public Napi::ObjectWrap { - public: MultiEncryptWrapper(const Napi::CallbackInfo& info) : Napi::ObjectWrap{info} { throw std::invalid_argument( - "MultiEncryptWrapper is all static and don't need to be constructed"); + "MultiEncryptWrapper is static and doesn't need to be constructed"); } static void Init(Napi::Env env, Napi::Object exports) { @@ -85,7 +84,7 @@ class MultiEncryptWrapper : public Napi::ObjectWrap { std::vector messages_sv(messages.begin(), messages.end()); std::vector recipients_sv(recipients.begin(), recipients.end()); - // Note: this function needs the first 2 args to be vector of sv explicitely + // Note: this function needs the first 2 args to be vector of sv explicitly return session::encrypt_for_multiple_simple( messages_sv, recipients_sv, ed25519SecretKey, domain, random_nonce); }); diff --git a/src/user_config.cpp b/src/user_config.cpp index 669081d..4f1937c 100644 --- a/src/user_config.cpp +++ b/src/user_config.cpp @@ -9,7 +9,6 @@ namespace session::nodeapi { -// using config::LogLevel; using config::UserProfile; void UserConfigWrapper::Init(Napi::Env env, Napi::Object exports) { diff --git a/src/utilities.hpp b/src/utilities.hpp index 45ebbe3..1a0d8bd 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -149,7 +149,6 @@ struct toJs_impl> { auto arr = Napi::Array::New(env, as_array.size()); for (size_t i = 0; i < as_array.size(); i++) arr[i] = toJs(env, as_array[i]); - return arr; } }; diff --git a/types/groups/groupmembers.d.ts b/types/groups/groupmembers.d.ts index 2f604a7..b414105 100644 --- a/types/groups/groupmembers.d.ts +++ b/types/groups/groupmembers.d.ts @@ -55,7 +55,7 @@ declare module 'libsession_util_nodejs' { // setters memberSetNameTruncated: (pubkeyHex: PubkeyType, newName: string) => void; - /** A member invite states defaults to invite-not-sent. Use this function to mark that you've sent one, or at least tried (failed: boolean)*/ + /** A member's invite state defaults to invite-not-sent. Use this function to mark that you've sent one, or at least tried (failed: boolean)*/ memberSetInvited: (pubkeyHex: PubkeyType, failed: boolean) => void; /** User has accepted an invitation and is now a regular member of the group */ memberSetAccepted: (pubkeyHex: PubkeyType) => void; diff --git a/types/groups/index.d.ts b/types/groups/index.d.ts index 818192a..311fdbb 100644 --- a/types/groups/index.d.ts +++ b/types/groups/index.d.ts @@ -1,2 +1 @@ -/// -/// +/// \ No newline at end of file diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 4e4cea7..35e657e 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -7,9 +7,22 @@ declare module 'libsession_util_nodejs' { export type ConfirmKeysPush = [data: Uint8Array, hash: string, timestampMs: number]; export type GroupWrapperConstructor = { - userEd25519Secretkey: Uint8Array; // (len 64) - groupEd25519Pubkey: Uint8Array; // the ed25519 pubkey without the 03 prefix (len 32) - groupEd25519Secretkey: Uint8Array | null; // the ed25519 privkey if we have it (len 64) (comes from usergroup wrapper if we have it) + /** + * The user's ed25519 secret key, length 64. + */ + userEd25519Secretkey: Uint8Array; + /** + * The group ed25519 pubkey without the 03 prefix, length 32. + */ + groupEd25519Pubkey: Uint8Array; + /** + * The group ed25519 priv key if we have it (len 64). Having this means we have admin rights in the group. + * This usually comes from the user group wrapper if we have it. + */ + groupEd25519Secretkey: Uint8Array | null; + /** + * The unified dumps (as saved in the db) for this group. i.e. Keys, Members and Info concatenated, see MetaGroupWrapper::metaDump for details. + */ metaDumped: Uint8Array | null; }; diff --git a/types/shared.d.ts b/types/shared.d.ts index 863755a..69fbd47 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -6,7 +6,7 @@ declare module 'libsession_util_nodejs' { /** * Allow a single type to be Nullable. i.e. string => string | null */ - type Nullable = T | null; + export type Nullable = T | null; /** * Allow all the fields of a type to be -themselves- nullable. diff --git a/types/user/usergroups.d.ts b/types/user/usergroups.d.ts index 976a0b6..53cfa3a 100644 --- a/types/user/usergroups.d.ts +++ b/types/user/usergroups.d.ts @@ -36,17 +36,38 @@ declare module 'libsession_util_nodejs' { name: string; // human-readable; this should normally always be set, but in theory could be set to an empty string. encPubkey: Uint8ArrayLen32; // bytes (32 or empty) encSeckey: Uint8Array; // bytes (32 or empty) - // disappearingTimerSeconds: number; // in seconds, 0 == disabled. members: Array; }; type UserGroupsGet = BaseUserGroup & { - pubkeyHex: GroupPubkeyType; // The group "session id" (33 bytes), starting with 03. - secretKey: Uint8ArrayLen64 | null; // len 64 - authData: Uint8ArrayLen100 | null; // len 100 + /** + * The group "session id" (33 bytes), starting with 03. + */ + pubkeyHex: GroupPubkeyType; + /** + * The group admin secret key if we have it, length 64. + */ + secretKey: Uint8ArrayLen64 | null; + /** + * The group auth data we were given if we have it, length 100. + */ + authData: Uint8ArrayLen100 | null; + /** + * The group name. + */ name: string | null; - invitePending: boolean; // tracks `db.approved`. libsession allows this field for all groups (including communities, but we don't need it for more) - kicked: boolean; // Note: if the group was `destroyed` this will be false, but `destroyed` will be true + /** + * True if the invite is pending, i.e. we've received it but haven't approved or auto-approved it yet. + */ + invitePending: boolean; + /** + * If we were kicked from that group, this will be true. + * Note: if the group was `destroyed` this will be false, but `destroyed` will be true + */ + kicked: boolean; + /** + * If the group was destroyed, this will be true + */ destroyed: boolean; }; From 1911a48d9906d39ac3f9e154dbdd07430003000c Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 20 Nov 2024 10:45:46 +1100 Subject: [PATCH 63/64] fix: disable sed on windows as not needed without libquic branch --- .github/workflows/test.yml | 22 ++++++---------------- src/groups/meta_group_wrapper.cpp | 1 + types/groups/metagroup.d.ts | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7da82da..52d63c0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,16 +31,6 @@ jobs: with: submodules: 'recursive' - # this should only be needed on ubuntu-20.04 - - # - name: Force g++10 to be used - # if: runner.os == 'Linux' - # shell: bash - # run: | - # sudo apt install -y libstdc++-10-dev g++-10 - # sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10 - # sudo update-alternatives --set gcc /usr/bin/gcc-10 - - name: Install node uses: actions/setup-node@v3 with: @@ -60,12 +50,12 @@ jobs: run: | yarn global add node-gyp@latest - - name: sed it - if: runner.os == 'Windows' - shell: bash - run: | - sed -i "s/target_compile_options(oxen-logging-warnings INTERFACE/#target_compile_options(oxen-logging-warnings INTERFACE/" libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt - cat libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt + # - name: sed it + # if: runner.os == 'Windows' + # shell: bash + # run: | + # sed -i "s/target_compile_options(oxen-logging-warnings INTERFACE/#target_compile_options(oxen-logging-warnings INTERFACE/" libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt + # cat libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt - name: build libsession-util-nodejs shell: bash diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 38a4a11..7de74ca 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -391,6 +391,7 @@ Napi::Value MetaGroupWrapper::memberGetAll(const Napi::CallbackInfo& info) { return allMembers; }); } + Napi::Value MetaGroupWrapper::memberGetAllPendingRemovals(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { std::vector allMembersRemoved; diff --git a/types/groups/metagroup.d.ts b/types/groups/metagroup.d.ts index 35e657e..f812070 100644 --- a/types/groups/metagroup.d.ts +++ b/types/groups/metagroup.d.ts @@ -104,7 +104,6 @@ declare module 'libsession_util_nodejs' { public memberSetProfilePicture: MetaGroupWrapper['memberSetProfilePicture']; // keys - public keysNeedsRekey: MetaGroupWrapper['keysNeedsRekey']; public keyRekey: MetaGroupWrapper['keyRekey']; public loadKeyMessage: MetaGroupWrapper['loadKeyMessage']; @@ -118,6 +117,7 @@ declare module 'libsession_util_nodejs' { export type MetaGroupActionsType = | ['init', GroupWrapperConstructor] + // shared actions | MakeActionCall | MakeActionCall From 771f3439e261450b2ebcadac63887424bb398fff Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 20 Nov 2024 12:08:26 +1100 Subject: [PATCH 64/64] fix: windows build --- src/groups/meta_group_wrapper.cpp | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 7de74ca..c6e2752 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -409,7 +409,7 @@ Napi::Value MetaGroupWrapper::memberGet(const Napi::CallbackInfo& info) { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberGet"); return meta_group->members->get(pubkeyHex); }); } @@ -419,7 +419,7 @@ Napi::Value MetaGroupWrapper::memberGetOrConstruct(const Napi::CallbackInfo& inf assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberGetOrConstruct"); return meta_group->members->get_or_construct(pubkeyHex); }); } @@ -429,7 +429,7 @@ Napi::Value MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& in assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberConstructAndSet"); auto created = meta_group->members->get_or_construct(pubkeyHex); meta_group->members->set(created); return created; @@ -441,8 +441,8 @@ void MetaGroupWrapper::memberSetNameTruncated(const Napi::CallbackInfo& info) { assertIsString(info[0]); assertIsString(info[1]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto newName = toCppString(info[1], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetNameTruncated pubkeyHex"); + auto newName = toCppString(info[1], "memberSetNameTruncated newName"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_name(newName); @@ -455,8 +455,8 @@ void MetaGroupWrapper::memberSetInvited(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertIsString(info[0]); assertIsBoolean(info[1]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); - auto failed = toCppBoolean(info[1], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetInvited"); + auto failed = toCppBoolean(info[1], "memberSetInvited"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { @@ -471,7 +471,7 @@ void MetaGroupWrapper::memberSetAccepted(const Napi::CallbackInfo& info) { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetAccepted"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_accepted(); @@ -484,7 +484,7 @@ void MetaGroupWrapper::memberSetPromoted(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetPromoted"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_promoted(); @@ -497,7 +497,7 @@ void MetaGroupWrapper::memberSetPromotionSent(const Napi::CallbackInfo& info) { wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetPromotionSent"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_promotion_sent(); @@ -510,7 +510,7 @@ void MetaGroupWrapper::memberSetPromotionFailed(const Napi::CallbackInfo& info) wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetPromotionFailed"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_promotion_failed(); @@ -523,7 +523,7 @@ void MetaGroupWrapper::memberSetPromotionAccepted(const Napi::CallbackInfo& info wrapExceptions(info, [&] { assertInfoLength(info, 1); assertIsString(info[0]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetPromotionAccepted"); auto m = this->meta_group->members->get(pubkeyHex); if (m) { m->set_promotion_accepted(); @@ -538,7 +538,7 @@ void MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) { assertIsString(info[0]); assertIsObject(info[1]); - auto pubkeyHex = toCppString(info[0], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(info[0], "memberSetProfilePicture"); auto profilePicture = profile_pic_from_object(info[1]); auto m = this->meta_group->members->get(pubkeyHex); @@ -557,11 +557,11 @@ void MetaGroupWrapper::membersMarkPendingRemoval(const Napi::CallbackInfo& info) assertIsArray(toUpdateJSValue); assertIsBoolean(withMessageJSValue); - bool withMessages = toCppBoolean(withMessageJSValue, __PRETTY_FUNCTION__); + bool withMessages = toCppBoolean(withMessageJSValue, "membersMarkPendingRemoval"); auto toUpdateJS = toUpdateJSValue.As(); for (uint32_t i = 0; i < toUpdateJS.Length(); i++) { - auto pubkeyHex = toCppString(toUpdateJS[i], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(toUpdateJS[i], "membersMarkPendingRemoval"); auto existing = this->meta_group->members->get(pubkeyHex); if (existing) { existing->set_removed(withMessages); @@ -581,7 +581,7 @@ Napi::Value MetaGroupWrapper::memberEraseAndRekey(const Napi::CallbackInfo& info auto toRemoveJS = toRemoveJSValue.As(); auto rekeyed = false; for (uint32_t i = 0; i < toRemoveJS.Length(); i++) { - auto pubkeyHex = toCppString(toRemoveJS[i], __PRETTY_FUNCTION__); + auto pubkeyHex = toCppString(toRemoveJS[i], "memberEraseAndRekey"); rekeyed |= this->meta_group->members->erase(pubkeyHex); } @@ -614,12 +614,12 @@ Napi::Value MetaGroupWrapper::loadKeyMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 3); assertIsString(info[0]); - assertIsUInt8Array(info[1], __PRETTY_FUNCTION__); - assertIsNumber(info[2], __PRETTY_FUNCTION__); + assertIsUInt8Array(info[1], "loadKeyMessage"); + assertIsNumber(info[2], "loadKeyMessage"); - auto hash = toCppString(info[0], __PRETTY_FUNCTION__); - auto data = toCppBuffer(info[1], __PRETTY_FUNCTION__); - auto timestamp_ms = toCppInteger(info[2], __PRETTY_FUNCTION__); + auto hash = toCppString(info[0], "loadKeyMessage"); + auto data = toCppBuffer(info[1], "loadKeyMessage"); + auto timestamp_ms = toCppInteger(info[2], "loadKeyMessage"); return meta_group->keys->load_key_message( hash, data, timestamp_ms, *(this->meta_group->info), *(this->meta_group->members)); @@ -657,7 +657,7 @@ Napi::Value MetaGroupWrapper::encryptMessages(const Napi::CallbackInfo& info) { encryptedMessages.reserve(arrayLength); for (uint32_t i = 0; i < plaintextsJS.Length(); i++) { - auto plaintext = toCppBuffer(plaintextsJS[i], __PRETTY_FUNCTION__); + auto plaintext = toCppBuffer(plaintextsJS[i], "encryptMessages"); encryptedMessages.push_back(this->meta_group->keys->encrypt_message(plaintext)); } @@ -668,9 +668,9 @@ Napi::Value MetaGroupWrapper::encryptMessages(const Napi::CallbackInfo& info) { Napi::Value MetaGroupWrapper::decryptMessage(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); + assertIsUInt8Array(info[0], "decryptMessage"); - auto ciphertext = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto ciphertext = toCppBuffer(info[0], "decryptMessage"); auto decrypted = this->meta_group->keys->decrypt_message(ciphertext); return decrypt_result_to_JS(info.Env(), decrypted); @@ -682,7 +682,7 @@ Napi::Value MetaGroupWrapper::makeSwarmSubAccount(const Napi::CallbackInfo& info assertInfoLength(info, 1); assertIsString(info[0]); - auto memberPk = toCppString(info[0], __PRETTY_FUNCTION__); + auto memberPk = toCppString(info[0], "makeSwarmSubAccount"); ustring subaccount = this->meta_group->keys->swarm_make_subaccount(memberPk); session::nodeapi::checkOrThrow( @@ -697,7 +697,7 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf assertInfoLength(info, 1); assertIsString(info[0]); - auto memberPk = toCppString(info[0], __PRETTY_FUNCTION__); + auto memberPk = toCppString(info[0], "swarmSubAccountToken"); ustring subaccount = this->meta_group->keys->swarm_subaccount_token(memberPk); session::nodeapi::checkOrThrow( @@ -710,9 +710,9 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf Napi::Value MetaGroupWrapper::swarmVerifySubAccount(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); + assertIsUInt8Array(info[0], "swarmVerifySubAccount"); - auto signingValue = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto signingValue = toCppBuffer(info[0], "swarmVerifySubAccount"); return this->meta_group->keys->swarm_verify_subaccount(signingValue); }); } @@ -720,9 +720,9 @@ Napi::Value MetaGroupWrapper::swarmVerifySubAccount(const Napi::CallbackInfo& in Napi::Value MetaGroupWrapper::loadAdminKeys(const Napi::CallbackInfo& info) { return wrapResult(info, [&] { assertInfoLength(info, 1); - assertIsUInt8Array(info[0], __PRETTY_FUNCTION__); + assertIsUInt8Array(info[0], "loadAdminKeys"); - auto secret = toCppBuffer(info[0], __PRETTY_FUNCTION__); + auto secret = toCppBuffer(info[0], "loadAdminKeys"); this->meta_group->keys->load_admin_key( secret, *(this->meta_group->info), *(this->meta_group->members)); return info.Env().Null(); @@ -750,7 +750,7 @@ Napi::Value MetaGroupWrapper::generateSupplementKeys(const Napi::CallbackInfo& i membersCpp.reserve(arrayLength); for (uint32_t i = 0; i < membersJS.Length(); i++) { - auto memberPk = toCppString(membersJS[i], __PRETTY_FUNCTION__); + auto memberPk = toCppString(membersJS[i], "generateSupplementKeys"); membersCpp.push_back(memberPk); } return this->meta_group->keys->key_supplement(membersCpp); @@ -763,8 +763,8 @@ Napi::Value MetaGroupWrapper::swarmSubaccountSign(const Napi::CallbackInfo& info assertIsUInt8Array(info[0], "swarmSubaccountSign 0"); assertIsUInt8Array(info[1], "swarmSubaccountSign 1"); - auto message = toCppBuffer(info[0], __PRETTY_FUNCTION__); - auto authdata = toCppBuffer(info[1], __PRETTY_FUNCTION__); + auto message = toCppBuffer(info[0], "swarmSubaccountSign message"); + auto authdata = toCppBuffer(info[1], "swarmSubaccountSign authdata"); auto subaccountSign = this->meta_group->keys->swarm_subaccount_sign(message, authdata); return subaccountSign;