Mocha - Error: Module did not self-register
I have integrated node-mac-permissions and am receiving an error when trying to test my app in a headless docker container run
xvfb-run yarn electron-mocha --no-sandbox --disable-gpu -R mocha-jenkins-reporter --require source-map-support/register out/test-main.js
Error:
✖ ERROR: Module did not self-register: '/home/jenkins/app/node_modules/node-mac-permissions/build/Release/permissions.node'.
I was able to narrow down the issue to the binding.gyp -> sources entry. There's no source/export provided for the permissions target for windows or Linux, which in the docker case, is causing the module to not "self-register". Resources used: https://stackoverflow.com/a/41283828 https://stackoverflow.com/a/55177338
I was able to solve it with this small patch that just creates a stub permissions.cc with empty export for win/linux sources
diff --git a/node_modules/node-mac-permissions/binding.gyp b/node_modules/node-mac-permissions/binding.gyp
index d5ba249..1e4bc00 100644
--- a/node_modules/node-mac-permissions/binding.gyp
+++ b/node_modules/node-mac-permissions/binding.gyp
@@ -1,7 +1,7 @@
{
"targets": [{
"target_name": "permissions",
- "sources": [ ],
+ "sources": [ "permissions.cc" ],
"conditions": [
['OS=="mac"', {
"sources": [
diff --git a/node_modules/node-mac-permissions/permissions.cc b/node_modules/node-mac-permissions/permissions.cc
new file mode 100644
index 0000000..5522c40
--- /dev/null
+++ b/node_modules/node-mac-permissions/permissions.cc
@@ -0,0 +1,7 @@
+#include <napi.h>
+
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
+ return exports;
+ }
+
+NODE_API_MODULE(permissions, Init)
\ No newline at end of file
I'm honestly not familiar with NAPI, and I'm not sure if the empty module export is correct. Alternatively, one could simply stub a function for every entry and just returns "authorized". A for-loop could easily improve it, but the approach, in general, feels messy to me.
#include <napi.h>
// Returns the user's home folder path.
Napi::Value GetAuthStatus(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
std::string auth_status = "authorized"
return Napi::Value::From(env, auth_status);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "getAuthStatus"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForContactsAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForCalendarAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForRemindersAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForFoldersAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForFullDiskAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForCameraAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForMicrophoneAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForSpeechRecognitionAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForPhotosAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForScreenCaptureAccess"),
Napi::Function::New(env, GetAuthStatus));
exports.Set(Napi::String::New(env, "askForAccessibilityAccess"),
Napi::Function::New(env, GetAuthStatus));
return exports;
}
NODE_API_MODULE(permissions, Init)
At the end of the day, I'm assuming I'm configuring something wrong considering how well maintained this project is (and thank you for it!)
Is node-mac-permissions supposed to be imported/required conditionally based on process.platform or something in the code?
@mmaietta hmm - this is only intended for use on macOS. I can try to poke at it to make sure it doesn't fall over on different platforms but i just assumed no one would try 😅
Your general approach is crudely correct but i might tweak it a bit - you're also welcome to send a PR if you're so inclined!
I found a better route!
I was inspired by another project that uses conditional binding dependent upon os.platfrom(). It keeps sources from being modified and makes it so imports on other OS' don't impact the binding itself (Since the .node is generated for all platforms anyways)
I have a local solution already done. Created a fork of this repo so I should have a PR ready by end of tomorrow 🙂
Note: the conditional binding is great because it allows us to retain typesafety of the import, as opposed to using a dynamic import in my local code which creates a Promisepermissions.AuthType as function params. That's the main advantage of my proposed approach