Example #1
0
                .chain((config) => {
                    const serviceDefs = config.services || {};

                    const registerFutures = Object.keys(serviceDefs).map((serviceName) => {
                        const serviceDef = serviceDefs[serviceName];
                        const {
                            path,
                            options = {},
                        } = serviceDef;

                        debug('service def: ', serviceName, serviceDef);

                        if (!path) {
                            // TODO: this should probably error
                            return Future.of(null);
                        }

                        const requirePath = resolvePath(path);

                        const Service = require(requirePath);
                        const service = Service(serviceName);

                        return this['service:register']({service}, this.source)
                            .chain(() => this.ask(service.id, 'configure', options))
                        ;
                    });

                    return Future.parallel(10, registerFutures);
                })
Example #2
0
                .chain((services) => {

                    debug('found services', services.map((s) => `${s.type}/${s.name}/${s.id}`));

                    // If a response is expected, we just send the message
                    // and wait for the future to resolve with the data.
                    // Otherwise, we return early and send the message on to
                    // its destination, forcing the future to execute

                    // TODO: watchers and interceptors
                    const futures =  services.map(
                        (service) => wrapFuture(service._inbox({
                            source,
                            action,
                            data,
                        }))
                            // here we are resolving with null in case of an error so
                            // that the rest of the discovery can complete succesfully.
                            // we filter the null values out after everything is reported.
                            // TODO: report the error
                            .chainRej((err) => {
                                debug('discover resulted in an error', err);
                                return Future.of(null);
                            })
                    );

                    // TODO: make number of simultaneous message sends configurable
                    //       at the kernel layer
                    const sendFuture = Future.parallel(10, futures).map((results) => {
                        // remove null values here...
                        // TODO: should also filter non-valid results and report problems
                        return results.filter((result) => !!result);
                    });

                    if (expectResponse) {
                        return sendFuture;
                    } else {
                        sendFuture.fork(noop, noop);
                        return Future.of(null);
                    }
                })
Example #3
0
                // branch to simply resolve with the error.
                // TODO: consider reporting any errors somehow

                return this.findService(subscription.source.id)
                    .chain((service) => wrapFuture(service._inbox({
                        source,
                        action: subscription.action,
                        data,
                    })))
                    .chainRej((err) => Future.of(err))
                ;
            });

            // We don't return the broadcast future since we don't want to bubble
            // any errors back up to the caller.
            const broadcast = Future.parallel(5, futures);

            broadcast.fork(noop, noop);

            return Future.of(null);
        },
        sendPointToPoint(destination, action, data, source, expectResponse) {
            debug('send p2p', destination, action);

            return this.findService(destination)
                .chain((service) => {

                    // If a response is expected, we just send the message
                    // and wait for the future to resolve with the data.
                    // Otherwise we return early and send the message on to
                    // its destination, forcing the future to execute
Example #4
0
module.exports = exports = function createUI(options, definitions) {
    const {
        rooturl = 'http://localhost:8081',
        apiurl,
        basepath = '/',
        title = 'Couer Application',
        manageMenuTitle = 'Manage',
        clientPaths = {},
        themepath = resolve(__dirname, '../client/src/css/themes/couer/theme.css'),
    } = options;

    const ui = {
        title,
        basepath: R.last(basepath) === '/' ? R.init(basepath) : basepath,
        apiurl,
        definitions,
    };

    definitions.forEach((def) => {
        Object.defineProperty(def, 'ui', {
            get: function() { return ui; },
            enumerable: true,
        });
    });

    const viewdefs = definitions.reduce((res, def) => {
        const data = def.definition(ui);

        return res.concat(Array.isArray(data) ? data : [data]);
    }, []);

    const viewpaths = Object.assign({
        table: resolve(__dirname, '../client/src/js/views/TableView'),
        // display: resolve(__dirname, '../client/src/js/views/DisplayView.js'),
        form: resolve(__dirname, '../client/src/js/views/FormView.js'),
        // dashboard: resolve(__dirname, '../client/src/js/views/DashboardView.js'),
        // 404: resolve(__dirname, '../client/src/js/views/NotFoundView.js'),
        // login: resolve(__dirname, '../client/src/js/views/LoginView.js'),
    }, clientPaths);


    const menulinks = [[manageMenuTitle, viewdefs.reduce((res, def) => {
        if (!def.menuTitle) {
            return res;
        }

        return res.concat([[def.menuTitle, def.path, def.menuIcon || '']]);
    }, [])]];

    const loginview = viewdefs.reduce((res, def) => {
        if (!res && def.islogin) {
            return def;
        }

        return res;
    }, null);

    const contextmenus = viewdefs.reduce((res, def) => {
        if (def.contextKey) {
            if (!res[def.contextKey]) {
                res[def.contextKey] = [def.contextKey, []];
            }

            res[def.contextKey][1].push([def.contextTitle, def.path, def.contextIcon || '']);

        }

        return res;
    }, {});

    const data = {views: viewdefs, menulinks, contextmenus, title, loginview, themepath};
    const tmpd = resolve(tmpdir(), `./${process.pid}-${Date.now()}`);
    const tmpjsd = resolve(tmpd, './js');
    const dest = resolve(cwd(), './client');
    const destjsd = resolve(dest, './js');
    const destcssd = resolve(dest, './css');
    const destjsfile = resolve(destjsd, './index.js');
    const destcssfile = resolve(destcssd, './index.css');
    const tmpjs = resolve(tmpjsd, './index.js');
    const destassets = resolve(dest, './assets');

    const js = genjs(data, viewpaths);

    const mkdirs = Future.parallel(1, [
        Future.node((done) => mkdirp(destjsd, done)),
        Future.node((done) => mkdirp(destcssd, done)),
        Future.node((done) => mkdirp(destassets, done)),
        Future.node((done) => mkdirp(tmpjsd, done)),
    ]);

    let buildjs =
        mkdirs.chain(() => Future.node((done) => fs.writeFile(tmpjs, js, done))).chain(() => {

            const browserify = require('browserify');
            const b = browserify({
                // builtins,
            });
            b.add(tmpjs);
            const cssModulesify = require('css-modulesify');
            const FileSystemLoader = require('css-modulesify/file-system-loader');
            const originalFetch = FileSystemLoader.prototype.fetch;
            FileSystemLoader.prototype.fetch = function(_newPath, relativeTo, _trace) {
                if (_newPath.replace(/^["']|["']$/g, '') === '!theme') {
                    _newPath = themepath;
                }

                return originalFetch.call(this, _newPath, relativeTo, _trace);
            };

            // const assets = require('postcss-assets');

            b.plugin(cssModulesify, {
                rootDir: '/',
                output: destcssfile,
                generateScopedName: cssModulesify.generateShortName,
                before: [
                    'postcss-import',
                    // 'postcss-mixins',
                    // 'postcss-simple-vars',
                    'postcss-nested',
                ],
                after: [
                    // 'postcss-conditionals',
                    'postcss-calc',
                    'postcss-color-function',
                    // assets({
                    //     loadPaths: [resolve(__dirname, '../client/src/assets')],
                    // }),
                    // 'lost',
                ],
            });

            return Future.node(done => b.bundle(done))
                .chain((buffer) => {
                    return Future.node((done) => fs.writeFile(destjsfile, buffer, done));
                })
            ;
        })
    ;

    buildjs = Future.cache(buildjs);

    const staticServer = router.static('/', dest);

    return router.scope(basepath, Pipeline.build([
        router.scope('/_resource', Pipeline.build([
            (req, res) => buildjs.chain(() => staticServer(req, res)),
        ])),
        (req, res) => {
            // no post routes here
            if (!req.ismethod('GET')) {
                return next(req, res);
            }

            const root = trimTrailingSlash(`${rooturl}${basepath}`);
            debug('root:', root);

            const data = {
                title,
                root,
            };
            const html = genhtml(data);
            return done(req, res.html(html));
        },
    ]));
};