Using Add-on SDK modules outside of Add-on SDK

Hello.

More specifically, I need to use SDK modules (both built-in and packaged with my add-on) in process script (which have completely different scope rather than SDK) in SDK add-on.
The simplest way is:
const { require } = Components.utils.import('resource://gre/modules/commonjs/toolkit/require.js', {});
But it have several problems:

  • SDK modules knows nothing about your add-on. In particular, sdk/self will not work. I was working around this by including forked version of SDK’s self with hardcoded add-on ID. It worked good until (read below)
  • It seems that there is only one instance of commonjs Loader per process wich lives as long as current browser process. Also, Loader instance seems to have some cache so when add-on updates, Loader loads original version of your commonjs modules rather than updated. That’s the main issue with it.

So, the obvious solution is to instantiate your own Loader which, by the way, can know your add-on ID so it will not be needed to fork sdk/self etc.
But I don’t know how to do it properly.
I’ve tried this way:

const id = 'add-on_id';
let loaderModule = Components.utils.import('resource://gre/modules/commonjs/toolkit/loader.js');
let loader = loaderModule.Loader({
    paths: {
        'sdk/': 'resource://gre/modules/commonjs/sdk/',
        './': `resource://${ id.toLowerCase().replace('@', '-at-') }/lib/`,
        '': 'resource://gre/modules/commonjs/'
    },
    id,
    metadata: {
        'permissions': {
            'private-browsing': true
        }
    },
    modules: {
        'toolkit/loader': loaderModule
    },
});

let requirer = loaderModule.Module(requirerID, requirerURI);
let require = loaderModule.Require(loader, requirer);

But it doesn’t work. It loads build-in SDK modules but fails to load my own. It throws an exception which tells "Module `modulename` is not found at resource://gre/modules/commonjs/modulename.js" when I require it like this "require('./modulename')"
Also, I have no idea what requirerID and requirerURI are for.

I’ve tried to use Loader options from require(’@loader/options’) executed in regular SDK scope but this options looks even more weird. For example, in paths it has "./":"resource://add-on_id/" but not "./":"resource://add-on_id/lib/". And it doesn’t work too.

The only thing I can do is read the sources but it needs some time.
So, help will be appreciated.