Skip to content

Commit 687b3b4

Browse files
committed
feat: merged both PRs and fixed conflicts
1 parent e45798b commit 687b3b4

File tree

7 files changed

+236
-116
lines changed

7 files changed

+236
-116
lines changed

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,21 @@ if(MSVC)
4646
add_compile_definitions(NOMINMAX)
4747
endif()
4848

49+
50+
4951
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
5052
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC} "include/" "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-addon-api" "${CMAKE_CURRENT_SOURCE_DIR}/node_modules" "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-api-headers/include")
5153

5254
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
5355
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB} ${LIBSESSION_STATIC_BUNDLE_LIBS})
5456

57+
58+
# if(UNIX AND NOT APPLE)
59+
# # Add switch-enum warnings as errors on Linux (see __builtin_unreachable calls)
60+
# target_compile_options(${PROJECT_NAME} PRIVATE -Werror=switch-enum)
61+
# endif()
62+
63+
5564
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
5665
# Generate node.lib
5766
execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})

include/pro/pro.hpp

Lines changed: 106 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,71 @@
55

66
#include <vector>
77

8-
#include "../../node_modules/node-addon-api/napi.h"
9-
#include "../meta/meta_base_wrapper.hpp"
10-
#include "../utilities.hpp"
11-
#include "./types.hpp"
128
#include "meta/meta_base_wrapper.hpp"
9+
#include "pro/types.hpp"
1310
#include "session/pro_backend.h"
1411
#include "session/pro_backend.hpp"
1512
#include "session/session_protocol.h"
1613
#include "session/session_protocol.hpp"
14+
#include "utilities.hpp"
1715

1816
namespace session::nodeapi {
19-
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v);
20-
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v);
21-
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PLAN v);
22-
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v);
23-
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v);
17+
18+
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v);
19+
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v);
20+
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_PLAN v);
21+
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v);
22+
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v);
23+
24+
template <>
25+
struct toJs_impl<pro_backend::ProRevocationItem> {
26+
auto operator()(const Napi::Env& env, pro_backend::ProRevocationItem i) const {
27+
28+
auto obj = Napi::Object::New(env);
29+
obj["genIndexHashB64"] = toJs(env, to_base64(i.gen_index_hash));
30+
obj["expiryUnixTsMs"] = toJs(env, i.expiry_unix_ts);
31+
32+
return obj;
33+
}
34+
};
35+
36+
template <>
37+
struct toJs_impl<pro_backend::ProPaymentItem> {
38+
auto operator()(const Napi::Env& env, pro_backend::ProPaymentItem p) const {
39+
40+
auto obj = Napi::Object::New(env);
41+
obj["status"] = toJs(env, proBackendEnumToString(p.status));
42+
obj["plan"] = toJs(env, proBackendEnumToString(p.plan));
43+
obj["paymentProvider"] = toJs(env, proBackendEnumToString(p.payment_provider));
44+
45+
obj["autoRenewing"] = toJs(env, p.auto_renewing);
46+
obj["unredeemedTsMs"] = toJs(env, p.unredeemed_unix_ts);
47+
obj["redeemedTsMs"] = toJs(env, p.redeemed_unix_ts);
48+
obj["expiryTsMs"] = toJs(env, p.expiry_unix_ts);
49+
obj["gracePeriodDurationMs"] = toJs(env, p.grace_period_duration_ms.count());
50+
obj["platformRefundExpiryTsMs"] = toJs(env, p.platform_refund_expiry_unix_ts);
51+
obj["revokedTsMs"] = toJs(env, p.revoked_unix_ts);
52+
53+
obj["googlePaymentToken"] = toJs(env, p.google_payment_token);
54+
obj["appleOriginalTxId"] = toJs(env, p.apple_original_tx_id);
55+
obj["appleTxId"] = toJs(env, p.apple_tx_id);
56+
obj["appleWebLineOrderId"] = toJs(env, p.apple_web_line_order_id);
57+
58+
return obj;
59+
}
60+
};
61+
62+
template <>
63+
struct toJs_impl<pro_backend::ResponseHeader> {
64+
auto operator()(const Napi::Env& env, pro_backend::ResponseHeader r) const {
65+
66+
auto obj = Napi::Object::New(env);
67+
obj["status"] = toJs(env, r.status);
68+
obj["errors"] = toJs(env, r.errors);
69+
70+
return obj;
71+
}
72+
};
2473

2574
class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
2675

@@ -40,28 +89,32 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
4089
"proFeaturesForMessage",
4190
static_cast<napi_property_attributes>(
4291
napi_writable | napi_configurable)),
92+
93+
// Pro requests
4394
StaticMethod<&ProWrapper::proProofRequestBody>(
4495
"proProofRequestBody",
4596
static_cast<napi_property_attributes>(
4697
napi_writable | napi_configurable)),
47-
StaticMethod<&ProWrapper::proProofResponseBody>(
48-
"proProofResponseBody",
49-
static_cast<napi_property_attributes>(
50-
napi_writable | napi_configurable)),
5198
StaticMethod<&ProWrapper::proRevocationsRequestBody>(
5299
"proRevocationsRequestBody",
53100
static_cast<napi_property_attributes>(
54101
napi_writable | napi_configurable)),
55-
StaticMethod<&ProWrapper::proRevocationsResponseBody>(
56-
"proRevocationsResponseBody",
57-
static_cast<napi_property_attributes>(
58-
napi_writable | napi_configurable)),
59102
StaticMethod<&ProWrapper::proStatusRequestBody>(
60103
"proStatusRequestBody",
61104
static_cast<napi_property_attributes>(
62105
napi_writable | napi_configurable)),
63-
StaticMethod<&ProWrapper::proStatusResponseBody>(
64-
"proStatusResponseBody",
106+
107+
// Pro responses parsing
108+
StaticMethod<&ProWrapper::proProofParseResponse>(
109+
"proProofParseResponse",
110+
static_cast<napi_property_attributes>(
111+
napi_writable | napi_configurable)),
112+
StaticMethod<&ProWrapper::proRevocationsParseResponse>(
113+
"proRevocationsParseResponse",
114+
static_cast<napi_property_attributes>(
115+
napi_writable | napi_configurable)),
116+
StaticMethod<&ProWrapper::proStatusParseResponse>(
117+
"proStatusParseResponse",
65118
static_cast<napi_property_attributes>(
66119
napi_writable | napi_configurable)),
67120
});
@@ -170,7 +223,7 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
170223
});
171224
};
172225

173-
static Napi::Value proProofResponseBody(const Napi::CallbackInfo& info) {
226+
static Napi::Value proProofParseResponse(const Napi::CallbackInfo& info) {
174227
return wrapResult(info, [&] {
175228
// we expect arguments that match:
176229
// first: {
@@ -184,17 +237,14 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
184237
auto first = info[0].As<Napi::Object>();
185238

186239
if (first.IsEmpty())
187-
throw std::invalid_argument("proProofResponseBody first received empty");
240+
throw std::invalid_argument("proProofParseResponse first received empty");
188241

189-
assertIsString(first.Get("json"), "proProofResponseBody.jsonStr");
190-
auto json_str = toCppString(first.Get("json"), "proProofResponseBody.jsonStr");
191-
auto json = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str);
242+
assertIsString(first.Get("json"), "proProofParseResponse.json");
243+
auto json_str = toCppString(first.Get("json"), "proProofParseResponse.json");
244+
auto parsed = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str);
192245

193-
auto obj = Napi::Object::New(env);
194-
195-
obj["status"] = toJs(env, json.status);
196-
obj["errors"] = toJs(env, json.errors);
197-
obj["proof"] = json.errors.empty() ? toJs(env, json.proof) : env.Null();
246+
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
247+
obj["proof"] = parsed.errors.empty() ? toJs(env, parsed.proof) : env.Null();
198248

199249
return obj;
200250
});
@@ -227,13 +277,11 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
227277
.ticket = ticket.Uint32Value(),
228278
};
229279

230-
auto json = revocationsRequest.to_json();
231-
232-
return json;
280+
return revocationsRequest.to_json();
233281
});
234282
};
235283

236-
static Napi::Value proRevocationsResponseBody(const Napi::CallbackInfo& info) {
284+
static Napi::Value proRevocationsParseResponse(const Napi::CallbackInfo& info) {
237285
return wrapResult(info, [&] {
238286
// we expect arguments that match:
239287
// first: {
@@ -247,19 +295,16 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
247295
auto first = info[0].As<Napi::Object>();
248296

249297
if (first.IsEmpty())
250-
throw std::invalid_argument("proRevocationsResponseBody first received empty");
298+
throw std::invalid_argument("proRevocationsParseResponse first received empty");
251299

252-
assertIsString(first.Get("json"), "proRevocationsResponseBody.jsonStr");
253-
auto json_str = toCppString(first.Get("json"), "proRevocationsResponseBody.jsonStr");
254-
auto json = pro_backend::GetProRevocationsResponse::parse(json_str);
300+
assertIsString(first.Get("json"), "proRevocationsParseResponse.json");
301+
auto json_str = toCppString(first.Get("json"), "proRevocationsParseResponse.json");
302+
auto parsed = pro_backend::GetProRevocationsResponse::parse(json_str);
255303

256-
auto obj = Napi::Object::New(env);
257-
258-
obj["status"] = toJs(env, json.status);
259-
obj["errors"] = toJs(env, json.errors);
260-
obj["ticket"] = json.errors.empty() ? toJs(env, json.ticket) : env.Null();
261-
// FIXME: implement
262-
// obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null();
304+
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
305+
// if error is set, the body might not be parsable so don't try to use it
306+
obj["ticket"] = parsed.errors.size() ? env.Null() : toJs(env, parsed.ticket);
307+
obj["items"] = parsed.errors.size() ? env.Null() : toJs(env, parsed.items);
263308

264309
return obj;
265310
});
@@ -310,7 +355,7 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
310355
});
311356
};
312357

313-
static Napi::Value proStatusResponseBody(const Napi::CallbackInfo& info) {
358+
static Napi::Value proStatusParseResponse(const Napi::CallbackInfo& info) {
314359
return wrapResult(info, [&] {
315360
// we expect arguments that match:
316361
// first: {
@@ -324,30 +369,28 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
324369
auto first = info[0].As<Napi::Object>();
325370

326371
if (first.IsEmpty())
327-
throw std::invalid_argument("proStatusResponseBody first received empty");
372+
throw std::invalid_argument("proStatusParseResponse first received empty");
328373

329-
assertIsString(first.Get("json"), "proStatusResponseBody.jsonStr");
330-
auto json_str = toCppString(first.Get("json"), "proStatusResponseBody.jsonStr");
331-
auto json = pro_backend::GetProStatusResponse::parse(json_str);
374+
assertIsString(first.Get("json"), "proStatusParseResponse.json");
375+
auto json_str = toCppString(first.Get("json"), "proStatusParseResponse.json");
376+
auto parsed = pro_backend::GetProStatusResponse::parse(json_str);
332377

333-
auto obj = Napi::Object::New(env);
378+
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
334379

335-
obj["status"] = toJs(env, json.status);
336-
obj["errors"] = toJs(env, json.errors);
337-
// FIXME: implement
338-
// obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null();
339-
obj["userStatus"] = json.errors.empty()
340-
? toJs(env, ProBackendEnumToString(json.user_status))
380+
obj["items"] = parsed.errors.empty() ? toJs(env, parsed.items) : env.Null();
381+
obj["userStatus"] = parsed.errors.empty()
382+
? toJs(env, proBackendEnumToString(parsed.user_status))
341383
: env.Null();
342-
obj["errorReport"] = json.errors.empty()
343-
? toJs(env, ProBackendEnumToString(json.error_report))
384+
obj["errorReport"] = parsed.errors.empty()
385+
? toJs(env, proBackendEnumToString(parsed.error_report))
344386
: env.Null();
345-
obj["autoRenewing"] = json.errors.empty() ? toJs(env, json.auto_renewing) : env.Null();
387+
obj["autoRenewing"] =
388+
parsed.errors.empty() ? toJs(env, parsed.auto_renewing) : env.Null();
346389

347-
// FIXME: implement
348-
// obj["expiryUnixTsMs"] = json.errors.empty() ? toJs(env, json.expiry_unix_ts_ms) :
349-
// env.Null(); obj["gracePeriodDurationMs"] = json.errors.empty() ? toJs(env,
350-
// json.grace_period_duration_ms) : env.Null();
390+
obj["expiryTsMs"] =
391+
parsed.errors.empty() ? toJs(env, parsed.expiry_unix_ts_ms) : env.Null();
392+
obj["gracePeriodMs"] =
393+
parsed.errors.empty() ? toJs(env, parsed.grace_period_duration_ms) : env.Null();
351394

352395
return obj;
353396
});

include/utilities.hpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <fmt/format.h>
34
#include <napi.h>
45

56
#include <chrono>
@@ -239,6 +240,21 @@ struct toJs_impl<std::chrono::sys_seconds> {
239240
}
240241
};
241242

243+
template <>
244+
struct toJs_impl<std::chrono::milliseconds> {
245+
auto operator()(const Napi::Env& env, std::chrono::milliseconds t) const {
246+
return Napi::Number::New(env, t.count());
247+
}
248+
};
249+
250+
template <>
251+
struct toJs_impl<std::chrono::sys_time<std::chrono::milliseconds>> {
252+
auto operator()(
253+
const Napi::Env& env, std::chrono::sys_time<std::chrono::milliseconds> t) const {
254+
return Napi::Number::New(env, t.time_since_epoch().count());
255+
}
256+
};
257+
242258
// Returns {"url": "...", "key": buffer} object; both values will be Null if the pic is not set.
243259

244260
template <>
@@ -383,10 +399,11 @@ template <std::size_t N>
383399
std::array<uint8_t, N> from_hex_to_array(std::string x) {
384400
std::string as_hex = oxenc::from_hex(x);
385401
if (as_hex.size() != N) {
386-
throw std::invalid_argument(std::format(
387-
"from_hex_to_array: Decoded hex size mismatch: expected {}, got {}",
388-
N,
389-
as_hex.size()));
402+
throw std::invalid_argument(
403+
fmt::format(
404+
"from_hex_to_array: Decoded hex size mismatch: expected {}, got {}",
405+
N,
406+
as_hex.size()));
390407
}
391408

392409
std::array<uint8_t, N> result;
@@ -402,16 +419,15 @@ std::vector<unsigned char> from_base64_to_vector(std::string_view x);
402419
// Concept to match containers with a size() method
403420
template <typename T>
404421
concept HasSize = requires(T t) {
405-
{
406-
t.size()
407-
} -> std::convertible_to<size_t>;
422+
{t.size()}->std::convertible_to<size_t>;
408423
};
409424

410425
template <HasSize T>
411426
void assert_length(const T& x, size_t n, std::string_view base_identifier) {
412427
if (x.size() != n) {
413-
throw std::invalid_argument(std::format(
414-
"assert_length: expected {}, got {} for {}", n, x.size(), base_identifier));
428+
throw std::invalid_argument(
429+
fmt::format(
430+
"assert_length: expected {}, got {} for {}", n, x.size(), base_identifier));
415431
}
416432
}
417433

0 commit comments

Comments
 (0)