Place1 / node-gir

Node bindings to libgirepository
http://live.gnome.org/GObjectIntrospection
MIT License
27 stars 6 forks source link

opinions of using a Proxy for importing libs #8

Open Place1 opened 6 years ago

Place1 commented 6 years ago

The GJS GI implementation allows users to access GI libraries like the following:

const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;

Similarly, in Python GI libraries are imported using:

from gi.repository import GObject;
from gi.repository import Gtk;

In NodeJS we could achieve something similar using an ES6 Proxy object.

module.exports = new Proxy({}, {
  get: function(target, property, receiver) {
    return load(property);
});

this would allow users to import GI libraries in NodeJS using the following:

# common JS
const { GObject, Gtk } = require('node-gir');

# es6 import
import { GObject, Gtk } from 'node-gir';

and obviously we'd still allow users to require the load() function that node-gir currently exports so that they can import specific versions of GI libraries.

Using a Proxy would mean the library would have a minimum NodeJS version of 6.4 (when Proxy was introduced to node). I think this is acceptable as the previous LTS, version 4, is very old now and 6 is the following LTS version. It is likely that node-gir won't work on node versions before 6 anyway due to v8 API breakages. CI currently tests against version 6,8,9.

Thoughts

ewnd9 commented 6 years ago

As an alternative for consideration:

const GObject = require('node-gir/GObject');
const Gtk = require('node-gir/Gtk');

// node_modules/node-gir/Gtk.js
const { load } = require('./');
module.exports = load('Gtk', '3.0'); // how to support loading different versions?

update: fix typos

update 2: there's one downside, we can't create modules dynamically, so non-defaults like keybinder will be missing unless created manually (is there a registry of all gtk-bindings?)

Place1 commented 6 years ago

GJS handles versions like this:

imports.gi.versions.Gtk = "3.0";
const Gtk = imports.gi.Gtk;

So we could easily implement this using a Proxy in node-gir

# node-gir/src/index.js
const gi = {
    versions: {},
};

const handler = {
    get: function(target, name) {
        if (name === 'versions') {
            return gi.versions[name];
        }
        return load(name, gi.versions[name]);
    }
};

module.exports = new Proxy(gi, handler);

So someone can do the following if they want to set an explicit version (without using load() GJS style)

const gi = require('node-gir');
gi.versions.Gtk = '3.0';
const Gtk = gi.Gtk;

or just use default versions

const { Gtk, GObject } = require('node-gir');