refactor: switch to node-addon-api (#43)

This commit is contained in:
Robo 2024-02-01 04:32:03 +09:00 коммит произвёл GitHub
Родитель 4becd02b70
Коммит 0847fc6af5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 205 добавлений и 332 удалений

Просмотреть файл

@ -5,7 +5,7 @@ trigger:
include: ['*']
jobs:
- job: Windows64
- job: Windows
pool:
vmImage: 'windows-latest'
variables:
@ -13,14 +13,6 @@ jobs:
steps:
- template: build.yml
- job: Windows32
pool:
vmImage: 'windows-latest'
variables:
NPM_ARCH: 'ia32'
steps:
- template: build.yml
- job: macOS
pool:
vmImage: 'macOS-latest'
@ -34,9 +26,5 @@ jobs:
vmImage: 'Ubuntu-latest'
variables:
NPM_ARCH: 'x64'
dependsOn:
- Windows64
- Windows32
- macOS
steps:
- template: build.yml

Просмотреть файл

@ -1,16 +1,17 @@
{
"targets": [{
"target_name": "spdlog",
'dependencies': [
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
],
"sources": [
"src/main.cc",
"src/logger.cc"
],
"include_dirs": [
"<!(node -e \"require('nan')\")",
"<!(node -p \"require('node-addon-api').include_dir\")",
"deps/spdlog/include"
],
'cflags!': ['-fno-exceptions'],
'cflags_cc!': ['-fno-exceptions'],
'msvs_configuration_attributes': {
'SpectreMitigation': 'Spectre'
},

25
package-lock.json сгенерированный
Просмотреть файл

@ -11,7 +11,7 @@
"dependencies": {
"bindings": "^1.5.0",
"mkdirp": "^1.0.4",
"nan": "^2.17.0"
"node-addon-api": "7.1.0"
},
"devDependencies": {
"@types/mocha": "^10.0.0",
@ -649,11 +649,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
"node_modules/nanoid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
@ -666,6 +661,14 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/node-addon-api": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz",
"integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==",
"engines": {
"node": "^16 || ^18 || >= 20"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -1423,17 +1426,17 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
"nanoid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
"dev": true
},
"node-addon-api": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz",
"integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g=="
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",

Просмотреть файл

@ -8,7 +8,6 @@
"ui": "tdd"
},
"scripts": {
"dev": "cp -R ~/.node-gyp/$(node -p 'process.versions.node')/include/node deps/node",
"test": "mocha"
},
"repository": {
@ -20,9 +19,7 @@
"spdlog",
"logging",
"logger",
"log",
"fast",
"performance"
"log"
],
"author": "Microsoft",
"license": "MIT",
@ -33,7 +30,7 @@
"dependencies": {
"bindings": "^1.5.0",
"mkdirp": "^1.0.4",
"nan": "^2.17.0"
"node-addon-api": "7.1.0"
},
"devDependencies": {
"@types/mocha": "^10.0.0",

Просмотреть файл

@ -15,315 +15,180 @@
#include <Windows.h>
#endif
std::string utf8StringAsString(Nan::Utf8String&& str) {
return std::string(*str, str.length());
Napi::Object Logger::Init(Napi::Env env, Napi::Object exports) {
Napi::FunctionReference* constructor = new Napi::FunctionReference();
Napi::Function definition = DefineClass(env, "Logger", {
InstanceMethod<&Logger::GetLevel>("getLevel"),
InstanceMethod<&Logger::SetLevel>("setLevel"),
InstanceMethod<&Logger::Flush>("flush"),
InstanceMethod<&Logger::Drop>("drop"),
InstanceMethod<&Logger::SetPattern>("setPattern"),
InstanceMethod<&Logger::ClearFormatters>("clearFormatters"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::critical>>("critical"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::err>>("error"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::warn>>("warn"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::info>>("info"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::debug>>("debug"),
InstanceMethod<&Logger::Log<spdlog::level::level_enum::trace>>("trace"),
});
*constructor = Napi::Persistent(definition);
exports.Set("Logger", definition);
env.SetInstanceData<Napi::FunctionReference>(constructor);
return exports;
}
NAN_METHOD(setLevel) {
if (!info[0]->IsNumber()) {
return Nan::ThrowError(Nan::Error("Provide level"));
Logger::Logger(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<Logger>(info) {
Napi::Env env(info.Env());
if (!info[0].IsString()) {
throw Napi::Error::New(env, "Provide a logger name");
}
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
return Nan::ThrowError(Nan::Error("Invalid level"));
}
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
const std::string name = info[0].As<Napi::String>();
spdlog::set_level(level);
if (name == "rotating" || name == "rotating_async") {
if (!info[1].IsString() || !info[2].IsString()) {
throw Napi::Error::New(env, "Provide the log name and file name");
}
if (!info[3].IsNumber() || !info[4].IsNumber()) {
throw Napi::Error::New(env, "Provide the max size and max files");
}
const std::string logName = info[1].As<Napi::String>();
logger_ = spdlog::get(logName);
if (!logger_) {
#if defined(_WIN32)
const std::string utf8Filename = info[2].As<Napi::String>();
const int bufferLen = MultiByteToWideChar(
CP_UTF8, 0, utf8Filename.c_str(),
static_cast<int>(utf8Filename.size()), NULL, 0);
if (!bufferLen) {
throw Napi::Error::New(env, "Failed to determine buffer length for converting filename to wstring");
}
std::wstring fileName(bufferLen, 0);
const int status = MultiByteToWideChar(
CP_UTF8, 0, utf8Filename.c_str(),
static_cast<int>(utf8Filename.size()), &fileName[0], bufferLen);
if (!status) {
throw Napi::Error::New(env, "Failed to convert filename to wstring");
}
#else
const std::string fileName = info[2].As<Napi::String>();
#endif
if (logName == "rotating_async") {
logger_ = spdlog::rotating_logger_st<spdlog::async_factory>(
logName, fileName, static_cast<size_t>(info[3].As<Napi::Number>().Int64Value()),
static_cast<size_t>(info[4].As<Napi::Number>().Int64Value()));
} else {
logger_ = spdlog::rotating_logger_st(
logName, fileName, static_cast<size_t>(info[3].As<Napi::Number>().Int64Value()),
static_cast<size_t>(info[4].As<Napi::Number>().Int64Value()));
}
}
} else {
logger_ = spdlog::stdout_logger_st<spdlog::async_factory>(name);
}
}
NAN_METHOD(setFlushOn) {
if (!info[0]->IsNumber()) {
return Nan::ThrowError(Nan::Error("Provide flush level"));
}
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
return Nan::ThrowError(Nan::Error("Invalid level"));
}
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
spdlog::flush_on(level);
}
Nan::Persistent<v8::Function> Logger::constructor;
NAN_MODULE_INIT(Logger::Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Logger").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Nan::SetPrototypeMethod(tpl, "critical", Logger::Critical);
Nan::SetPrototypeMethod(tpl, "error", Logger::Error);
Nan::SetPrototypeMethod(tpl, "warn", Logger::Warn);
Nan::SetPrototypeMethod(tpl, "info", Logger::Info);
Nan::SetPrototypeMethod(tpl, "debug", Logger::Debug);
Nan::SetPrototypeMethod(tpl, "trace", Logger::Trace);
Nan::SetPrototypeMethod(tpl, "getLevel", Logger::GetLevel);
Nan::SetPrototypeMethod(tpl, "setLevel", Logger::SetLevel);
Nan::SetPrototypeMethod(tpl, "flush", Logger::Flush);
Nan::SetPrototypeMethod(tpl, "drop", Logger::Drop);
Nan::SetPrototypeMethod(tpl, "setPattern", Logger::SetPattern);
Nan::SetPrototypeMethod(tpl, "clearFormatters", Logger::ClearFormatters);
constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("Logger").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
Logger::Logger(std::shared_ptr<spdlog::logger> logger) : logger_(logger) {}
Logger::~Logger() {
if (logger_ == NULL) {
return;
}
try {
spdlog::drop(logger_->name());
if (logger_)
spdlog::drop(logger_->name());
} catch (...) {
// noop
}
logger_ = NULL;
}
NAN_METHOD(Logger::New) {
try {
if (info.IsConstructCall()) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a logger name"));
}
template<spdlog::level::level_enum level>
void Logger::Log(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
const std::string name = utf8StringAsString(Nan::Utf8String(info[0]));
std::shared_ptr<spdlog::logger> logger;
if (!info[0].IsString()) {
throw Napi::Error::New(env, "Provide a message to log");
}
if (name == "rotating" || name == "rotating_async") {
if (!info[1]->IsString() || !info[2]->IsString()) {
return Nan::ThrowError(
Nan::Error("Provide the log name and file name"));
}
if (!info[3]->IsNumber() || !info[4]->IsNumber()) {
return Nan::ThrowError(
Nan::Error("Provide the max size and max files"));
}
const std::string logName = utf8StringAsString(Nan::Utf8String(info[1]));
logger = spdlog::get(logName);
if (!logger) {
#if defined(_WIN32)
const std::string utf8Filename = utf8StringAsString(Nan::Utf8String(info[2]));
const int bufferLen = MultiByteToWideChar(
CP_UTF8, 0, utf8Filename.c_str(),
static_cast<int>(utf8Filename.size()), NULL, 0);
if (!bufferLen) {
return Nan::ThrowError(
Nan::Error("Failed to determine buffer length for converting filename to wstring"));
}
std::wstring fileName(bufferLen, 0);
const int status = MultiByteToWideChar(
CP_UTF8, 0, utf8Filename.c_str(),
static_cast<int>(utf8Filename.size()), &fileName[0], bufferLen);
if (!status) {
return Nan::ThrowError(
Nan::Error("Failed to convert filename to wstring"));
}
#else
const std::string fileName = utf8StringAsString(Nan::Utf8String(info[2]));
#endif
if (logName == "rotating_async") {
logger = spdlog::rotating_logger_st<spdlog::async_factory>(
logName, fileName, static_cast<size_t>(Nan::To<int64_t>(info[3]).FromJust()),
static_cast<size_t>(Nan::To<int64_t>(info[4]).FromJust()));
} else {
logger = spdlog::rotating_logger_st(
logName, fileName, static_cast<size_t>(Nan::To<int64_t>(info[3]).FromJust()),
static_cast<size_t>(Nan::To<int64_t>(info[4]).FromJust()));
}
}
} else {
logger = spdlog::stdout_logger_st<spdlog::async_factory>(name);
}
Logger *obj = new Logger(logger);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor);
info.GetReturnValue().Set(
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
if (logger_) {
std::string message = info[0].As<Napi::String>();
switch(level) {
case spdlog::level::level_enum::critical:
logger_->critical(message);
break;
case spdlog::level::level_enum::err:
logger_->error(message);
break;
case spdlog::level::level_enum::warn:
logger_->warn(message);
break;
case spdlog::level::level_enum::info:
logger_->info(message);
break;
case spdlog::level::level_enum::debug:
logger_->debug(message);
break;
case spdlog::level::level_enum::trace:
logger_->trace(message);
break;
}
} catch (const std::exception &ex) {
return Nan::ThrowError(Nan::Error(ex.what()));
} catch (...) {
return Nan::ThrowError(Nan::Error("Unknown error creating log file"));
}
}
NAN_METHOD(Logger::Critical) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
Napi::Value Logger::GetLevel(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
if (logger_) {
return Napi::Number::New(env, logger_->level());
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->critical(message);
}
info.GetReturnValue().Set(info.This());
return Napi::Number::New(env, 2);
}
NAN_METHOD(Logger::Error) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
void Logger::SetLevel(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
if (!info[0].IsNumber()) {
throw Napi::Error::New(env, "Provide level");
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->error(message);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Warn) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->warn(message);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Info) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->info(message);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Debug) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->debug(message);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Trace) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide a message to log"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
obj->logger_->trace(message);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::GetLevel) {
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
info.GetReturnValue().Set(obj->logger_->level());
}
}
NAN_METHOD(Logger::SetLevel) {
if (!info[0]->IsNumber()) {
return Nan::ThrowError(Nan::Error("Provide level"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
if (logger_) {
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
return Nan::ThrowError(Nan::Error("Invalid level"));
throw Napi::Error::New(env, "Invalid level");
}
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
obj->logger_->set_level(level);
logger_->set_level(level);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Flush) {
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
obj->logger_->flush();
void Logger::Flush(const Napi::CallbackInfo& info) {
if (logger_) {
logger_->flush();
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::Drop) {
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
const std::string name = obj->logger_->name();
obj->logger_ = NULL;
void Logger::Drop(const Napi::CallbackInfo& info) {
if (logger_) {
const std::string name = logger_->name();
logger_.reset();
spdlog::drop(name);
}
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(Logger::SetPattern) {
if (!info[0]->IsString()) {
return Nan::ThrowError(Nan::Error("Provide pattern"));
}
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
const std::string pattern = utf8StringAsString(Nan::Utf8String(info[0]));
void Logger::SetPattern(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
if (obj->logger_) {
obj->logger_->set_pattern(pattern);
if (!info[0].IsString()) {
throw Napi::Error::New(env, "Provide pattern");
}
info.GetReturnValue().Set(info.This());
const std::string pattern = info[0].As<Napi::String>();
if (logger_) {
logger_->set_pattern(pattern);
}
}
NAN_METHOD(Logger::ClearFormatters) {
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
if (obj->logger_) {
obj->logger_->set_formatter(
void Logger::ClearFormatters(const Napi::CallbackInfo& info) {
if (logger_) {
logger_->set_formatter(
std::unique_ptr<VoidFormatter>(new VoidFormatter()));
}
info.GetReturnValue().Set(info.This());
}

Просмотреть файл

@ -4,44 +4,32 @@
* license information.
*--------------------------------------------------------------------------------------------*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <nan.h>
#include <napi.h>
// Prevent child processes from inheriting the file handles
#define SPDLOG_PREVENT_CHILD_FD
#include <spdlog/spdlog.h>
NAN_METHOD(setLevel);
NAN_METHOD(setFlushOn);
class Logger : public Nan::ObjectWrap {
class Logger : public Napi::ObjectWrap<Logger> {
public:
static NAN_MODULE_INIT(Init);
static Napi::Object Init(Napi::Env env, Napi::Object exports);
explicit Logger(const Napi::CallbackInfo& info);
private:
explicit Logger(std::shared_ptr<spdlog::logger> logger);
friend class Napi::ObjectWrap<Logger>;
~Logger();
static NAN_METHOD(New);
template<spdlog::level::level_enum level>
void Log(const Napi::CallbackInfo& info);
static NAN_METHOD(Critical);
static NAN_METHOD(Error);
static NAN_METHOD(Warn);
static NAN_METHOD(Info);
static NAN_METHOD(Debug);
static NAN_METHOD(Trace);
static NAN_METHOD(GetLevel);
static NAN_METHOD(SetLevel);
static NAN_METHOD(Flush);
static NAN_METHOD(Drop);
static NAN_METHOD(SetPattern);
static NAN_METHOD(ClearFormatters);
static Nan::Persistent<v8::Function> constructor;
Napi::Value GetLevel(const Napi::CallbackInfo& info);
void SetLevel(const Napi::CallbackInfo& info);
void Flush(const Napi::CallbackInfo& info);
void Drop(const Napi::CallbackInfo& info);
void SetPattern(const Napi::CallbackInfo& info);
void ClearFormatters(const Napi::CallbackInfo& info);
std::shared_ptr<spdlog::logger> logger_;
};
@ -55,5 +43,3 @@ class VoidFormatter : public spdlog::formatter {
return spdlog::details::make_unique<VoidFormatter>();
}
};
#endif // !CONSOLE_H

Просмотреть файл

@ -4,15 +4,48 @@
* license information.
*--------------------------------------------------------------------------------------------*/
#include <nan.h>
#include <napi.h>
#include "logger.h"
NAN_MODULE_INIT(Init) {
Nan::Set(target, Nan::New("version").ToLocalChecked(), Nan::New(SPDLOG_VERSION));
Nan::SetMethod(target, "setLevel", setLevel);
Nan::SetMethod(target, "setFlushOn", setFlushOn);
void SetLevel(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
Logger::Init(target);
if (!info[0].IsNumber()) {
throw Napi::Error::New(env, "Provide level");
}
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
throw Napi::Error::New(env, "Invalid level");
}
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
spdlog::set_level(level);
}
NODE_MODULE(spdlog, Init)
void SetFlushOn(const Napi::CallbackInfo& info) {
Napi::Env env(info.Env());
if (!info[0].IsNumber()) {
throw Napi::Error::New(env, "Provide flush level");
}
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
throw Napi::Error::New(env, "Invalid level");
}
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
spdlog::flush_on(level);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("version", Napi::Number::New(env, SPDLOG_VERSION));
exports.Set("setLevel", Napi::Function::New(env, SetLevel));
exports.Set("setFlushOn", Napi::Function::New(env, SetFlushOn));
Logger::Init(env, exports);
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);