<commit_before>#!/usr/bin/env node

'use strict';

process.env.DEBUG = '*ERROR* *WARN* mediasoup* protoo*';

const http = require('http');
const url = require('url');

const debug = require('debug')('webfighter');
const debugerror = require('debug')('webfighter:ERROR');
const mediasoup = require('../../');
const protoo = require('protoo');
const sdpTransform = require('sdp-transform');

const LISTEN_IP = '0.0.0.0';
const LISTEN_PORT = 8080;

// protoo app
let app = protoo();

// mediasoup server
let server = mediasoup.Server({ numWorkers: 1 });
let room = server.Room();

// Node-WebSocket server options
let wsOptions =
{
	maxReceivedFrameSize     : 960000,  // 960 KBytes
	maxReceivedMessageSize   : 960000,
	fragmentOutgoingMessages : true,
	fragmentationThreshold   : 960000
};

// HTTP server
let httpServer = http.createServer((req, res) =>
{
	res.writeHead(404, 'Not Here');
	res.end();
});

httpServer.listen(LISTEN_PORT, LISTEN_IP);

// Handle WebSocket connections
app.websocket(httpServer, wsOptions, (info, accept, reject) =>
{
	// Let the client indicate username and uuid in the URL query
	let u = url.parse(info.req.url, true);
	let username = u.query.username;
	let uuid = u.query.uuid;

	if (username && uuid)
	{
		debug('accepting WebSocket connection [username:%s, uuid:%s, ip:%s, port:%d]',
			username, uuid, info.socket.remoteAddress, info.socket.remotePort);

		accept(username, uuid, null);
	}
	else
	{
		debugerror('rejecting WebSocket connection due to missing username/uuid');

		reject();
	}
});

// Handle new peers
app.on('online', (peer) =>
{
	debug('peer online: %s', peer);

	let mediaPeer = room.Peer(peer.username);

	mediaPeer.on('close', (error) =>
	{
		if (error)
			peer.close(3500, error.message);
		else
			peer.close();
	});

	peer.data.mediaPeer = mediaPeer;
});

// Handle disconnected peers
app.on('offline', (peer) =>
{
	debug('peer offline: %s', peer);

	// Remove from the room
	peer.data.mediaPeer.close();
});

// Handle PUT requests to /test-transport
app.put('/test-transport', function(req)
{
	let mediaPeer = req.peer.data.mediaPeer;
	let sdpOffer = req.data.sdp;
	let offer = sdpTransform.parse(sdpOffer);
	let answer = {};

	answer.version = 0;
	answer.origin = offer.origin;
	answer.name = 'mediasoup';
	answer.timing = { start: 0, stop: 0 };
	answer.groups = offer.groups;
	answer.msidSemantic = offer.msidSemantic;
	answer.icelite = 'ice-lite';
	answer.media = [];

	mediaPeer.createTransport({ udp: true, tcp: false })
		.then((transport) =>
		{
			offer.media.forEach((om) =>
			{
				let am = {};

				am.mid = om.mid;
				am.connection = { ip: '1.2.3.4', version: 4 };
				am.port = 12345;
				am.protocol = om.protocol;
				am.iceUfrag = transport.iceLocalParameters.usernameFragment;
				am.icePwd = transport.iceLocalParameters.password;
				am.candidates = [];

				transport.iceLocalCandidates.forEach((candidate) =>
				{
					let ac = {};

					ac.component = transport.iceComponent === 'RTP' ? 1 : 2;
					ac.foundation = candidate.foundation;
					ac.ip = candidate.ip;
					ac.port = candidate.port;
					ac.priority = candidate.priority;
					ac.transport = candidate.protocol;
					ac.type = candidate.type;

					if (candidate.tcpType)
						ac.tcpType = candidate.tcpType;

					am.candidates.push(ac);
				});

				// TODO: get it from transport
				am.fingerprint =
				{
					hash : '00:56:63:99:13:26:02:50:DA:F4:46:79:F7:9D:66:82:5A:90:A8:B2:35:9F:19:14:8D:6C:D4:7C:17:C7:BF:70',
					type : 'sha-256'
				};
				am.setup = 'passive';
				am.type = om.type;
				am.rtcpMux = 'rtcp-mux';
				am.rtcp = om.rtcp;
				am.rtcpFb = om.rtcpFb;
				am.rtp = om.rtp;
				am.fmtp = om.fmtp;
				am.direction = om.direction === 'recvonly' ? 'sendonly' : 'sendrecv';
				am.payloads = om.payloads;

				answer.media.push(am);
			});

			let data =
			{
				type : 'answer',
				sdp  : sdpTransform.write(answer)
			};

			req.reply(200, 'OK', data);
		})
		.catch((error) =>
		{
			req.reply(400, error.message);
			return;
		});
});
<commit_msg>tester: Improve server.js comments.<commit_after>#!/usr/bin/env node

'use strict';

process.env.DEBUG = '*ERROR* *WARN* mediasoup* protoo*';

const http = require('http');
const url = require('url');

const debug = require('debug')('webfighter');
const debugerror = require('debug')('webfighter:ERROR');
const mediasoup = require('../../');
const protoo = require('protoo');
const sdpTransform = require('sdp-transform');

const LISTEN_IP = '0.0.0.0';
const LISTEN_PORT = 8080;

// protoo app
let app = protoo();

// mediasoup server
let server = mediasoup.Server({ numWorkers: 1 });
let room = server.Room();

// Node-WebSocket server options
let wsOptions =
{
	maxReceivedFrameSize     : 960000,  // 960 KBytes
	maxReceivedMessageSize   : 960000,
	fragmentOutgoingMessages : true,
	fragmentationThreshold   : 960000
};

// HTTP server
let httpServer = http.createServer((req, res) =>
{
	res.writeHead(404, 'Not Here');
	res.end();
});

httpServer.listen(LISTEN_PORT, LISTEN_IP);

// Handle WebSocket connections
app.websocket(httpServer, wsOptions, (info, accept, reject) =>
{
	// Let the client indicate username and uuid in the URL query
	let u = url.parse(info.req.url, true);
	let username = u.query.username;
	let uuid = u.query.uuid;

	if (username && uuid)
	{
		debug('accepting WebSocket connection [username:%s, uuid:%s, ip:%s, port:%d]',
			username, uuid, info.socket.remoteAddress, info.socket.remotePort);

		accept(username, uuid, null);
	}
	else
	{
		debugerror('rejecting WebSocket connection due to missing username/uuid');

		reject();
	}
});

// Handle new peers
app.on('online', (peer) =>
{
	debug('peer online: %s', peer);

	// Create a mediasoup Peer instance
	let mediaPeer = room.Peer(peer.username);

	mediaPeer.on('close', (error) =>
	{
		if (error)
			peer.close(3500, error.message);
		else
			peer.close();
	});

	// Store the mediasoup Peer instance within the protoo peer
	peer.data.mediaPeer = mediaPeer;
});

// Handle disconnected peers
app.on('offline', (peer) =>
{
	debug('peer offline: %s', peer);

	// Remove from the room
	peer.data.mediaPeer.close();
});

// Handle PUT requests to /test-transport
app.put('/test-transport', function(req)
{
	// Retrieve the mediasoup Peer associated to the protoo peer who sent the request
	let mediaPeer = req.peer.data.mediaPeer;
	let sdpOffer = req.data.sdp;
	let offer = sdpTransform.parse(sdpOffer);
	let answer = {};

	answer.version = 0;
	answer.origin = offer.origin;
	answer.name = 'mediasoup';
	answer.timing = { start: 0, stop: 0 };
	answer.groups = offer.groups;
	answer.msidSemantic = offer.msidSemantic;
	answer.icelite = 'ice-lite';
	answer.media = [];

	mediaPeer.createTransport({ udp: true, tcp: false })
		.then((transport) =>
		{
			offer.media.forEach((om) =>
			{
				let am = {};

				am.mid = om.mid;
				am.connection = { ip: '1.2.3.4', version: 4 };
				am.port = 12345;
				am.protocol = om.protocol;
				am.iceUfrag = transport.iceLocalParameters.usernameFragment;
				am.icePwd = transport.iceLocalParameters.password;
				am.candidates = [];

				transport.iceLocalCandidates.forEach((candidate) =>
				{
					let ac = {};

					ac.component = transport.iceComponent === 'RTP' ? 1 : 2;
					ac.foundation = candidate.foundation;
					ac.ip = candidate.ip;
					ac.port = candidate.port;
					ac.priority = candidate.priority;
					ac.transport = candidate.protocol;
					ac.type = candidate.type;

					if (candidate.tcpType)
						ac.tcpType = candidate.tcpType;

					am.candidates.push(ac);
				});

				// TODO: get it from transport
				am.fingerprint =
				{
					hash : '00:56:63:99:13:26:02:50:DA:F4:46:79:F7:9D:66:82:5A:90:A8:B2:35:9F:19:14:8D:6C:D4:7C:17:C7:BF:70',
					type : 'sha-256'
				};
				am.setup = 'passive';
				am.type = om.type;
				am.rtcpMux = 'rtcp-mux';
				am.rtcp = om.rtcp;
				am.rtcpFb = om.rtcpFb;
				am.rtp = om.rtp;
				am.fmtp = om.fmtp;
				am.direction = om.direction === 'recvonly' ? 'sendonly' : 'sendrecv';
				am.payloads = om.payloads;

				answer.media.push(am);
			});

			let data =
			{
				type : 'answer',
				sdp  : sdpTransform.write(answer)
			};

			req.reply(200, 'OK', data);
		})
		.catch((error) =>
		{
			req.reply(400, error.message);
			return;
		});
});
<|endoftext|>


<commit_before>
var fs = require('fs'),
	path = require('path'),
	async = require('async'),
	routeCount,
	_renderTemplate;

module.exports = function (app, options, siteSandal, renderTemplate, logger) {

	return function (callback) {

		_renderTemplate = renderTemplate;
		routeCount = 0;

		if (!fs.existsSync(options.routePath) || !fs.statSync(options.routePath).isDirectory()) return callback();

		async.each(fs.readdirSync(options.routePath), function (file, fileCallback) {
			loadFolder(app, options.routePath, file, siteSandal	, fileCallback)
		}, function (err) {
			if (err) return callback(err);
			logger.info('Loading ' + routeCount + ' routes done');
			callback();
		});

	};

};

function loadFolder(app, parentDir, file, sandal, callback) {

	var routeDir = path.join(parentDir, file),
		routePath = path.join(routeDir, file + '.js'),
		templatePath = path.join(routeDir, file + '.html'),
		route;

	if (!fs.existsSync(routeDir) || !fs.statSync(routeDir).isDirectory()) return callback();

	async.each(fs.readdirSync(routeDir), function (file, fileCallback) {
		loadFolder(app, routeDir, file, sandal, fileCallback)
	}, function (err) {

		if (err) callback(err);
		if (!fs.existsSync(routePath) || !fs.statSync(routePath).isFile()) return callback();

		route = require(routePath);

		resolveRoute(sandal, route, function (err, resolvedRoute) {
			if (err) return callback(err);
			registerRoute(app, resolvedRoute, templatePath, callback);
		});

	});

}

function resolveRoute(sandal, route, callback) {
	if (typeof route === 'function') {
		sandal.resolveAsFactory(route, callback);
	} else {
		callback(null, route);
	}
}

function registerRoute(app, route, templatePath, callback) {

	routeCount++;

	if (route.handler) {
		app.get(route.path, route.handler);
		return callback();
	}

	app.get(route.path, function(req, res, next){
		var test = route.test || function (testRequest, testCallback) { testCallback(null, true); },
			factory = route.factory || function (testRequest, factoryCallback) { factoryCallback(null, {}); };
		var that = {};
		test.bind(that)(req, function (err, result) {
			if (err) return next(err);
			if (!result) return next();
			factory.bind(that)(req, function (err, model, options) {
				if (err) return next(err);
				options = options || {};
				if (options.template) templatePath = path.join(templatePath, '../', options.template);
				_renderTemplate(templatePath, model, function (err, html) {
					if (err) return next(err);
					res.set({
						'Content-Type': 'text/html'
					});
					res.send(html);
				});
			});

		});
	});

	callback();

}<commit_msg>Support for other methods than get<commit_after>
var fs = require('fs'),
	path = require('path'),
	async = require('async'),
	routeCount,
	_renderTemplate;

module.exports = function (app, options, siteSandal, renderTemplate, logger) {

	return function (callback) {

		_renderTemplate = renderTemplate;
		routeCount = 0;

		if (!fs.existsSync(options.routePath) || !fs.statSync(options.routePath).isDirectory()) return callback();

		async.each(fs.readdirSync(options.routePath), function (file, fileCallback) {
			loadFolder(app, options.routePath, file, siteSandal	, fileCallback)
		}, function (err) {
			if (err) return callback(err);
			logger.info('Loading ' + routeCount + ' routes done');
			callback();
		});

	};

};

function loadFolder(app, parentDir, file, sandal, callback) {

	var routeDir = path.join(parentDir, file),
		routePath = path.join(routeDir, file + '.js'),
		templatePath = path.join(routeDir, file + '.html'),
		route;

	if (!fs.existsSync(routeDir) || !fs.statSync(routeDir).isDirectory()) return callback();

	async.each(fs.readdirSync(routeDir), function (file, fileCallback) {
		loadFolder(app, routeDir, file, sandal, fileCallback)
	}, function (err) {

		if (err) callback(err);
		if (!fs.existsSync(routePath) || !fs.statSync(routePath).isFile()) return callback();

		route = require(routePath);

		resolveRoute(sandal, route, function (err, resolvedRoute) {
			if (err) return callback(err);
			registerRoute(app, resolvedRoute, templatePath, callback);
		});

	});

}

function resolveRoute(sandal, route, callback) {
	if (typeof route === 'function') {
		sandal.resolveAsFactory(route, callback);
	} else {
		callback(null, route);
	}
}

function registerRoute(app, route, templatePath, callback) {

	routeCount++;

	var method = 'get';

	if (route.method) {
		method = route.method.toLowerCase();
	}

	if (route.handler) {
		app[method](route.path, route.handler);
		return callback();
	}

	app[method](route.path, function(req, res, next){
		var test = route.test || function (testRequest, testCallback) { testCallback(null, true); },
			factory = route.factory || function (testRequest, factoryCallback) { factoryCallback(null, {}); };
		var that = {};
		test.bind(that)(req, function (err, result) {
			if (err) return next(err);
			if (!result) return next();
			factory.bind(that)(req, function (err, model, options) {
				if (err) return next(err);
				options = options || {};
				if (options.template) templatePath = path.join(templatePath, '../', options.template);
				_renderTemplate(templatePath, model, function (err, html) {
					if (err) return next(err);
					res.set({
						'Content-Type': 'text/html'
					});
					res.send(html);
				});
			});

		});
	});

	callback();

}<|endoftext|>


<commit_before>/**
 * Created by KlimMalgin on 21.10.2014.
 */
'use strict';

var assert = require("assert");
require("./Morphine");

describe('Public API tests', function () {
    //var PublicApi = MorphineShareApi.CommonPrototypeMixin;

    describe('Morphine constructor', function () {

        it('Create from object', function () {
            var source = {
                myObject: {
                    start: {
                        value: 'start object value'
                    },
                    end: {
                        value: 'end object value'
                    }
                },
                myArray: [
                    {
                        index: 0,
                        value: 96
                    },
                    {
                        index: 1,
                        value: 'text value'
                    }
                ]
            };
            var morph = new Morphine(source);
            assert.equal(morph.has('myObject.start.value'), true, 'Объект содержит структуру "myObject.start.value"');
            assert.equal(morph.get('myObject.start.value'), 'start object value', 'Структура "myObject.start.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myObject.end.value'), true, 'Объект содержит структуру "myObject.end.value"');
            assert.equal(morph.get('myObject.end.value'), 'end object value', 'Структура "myObject.end.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.0.index'), true, 'Объект содержит структуру "myArray.0.index"');
            assert.equal(morph.get('myArray.0.index'), 0, 'Структура "myArray.0.index" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.0.value'), true, 'Объект содержит структуру "myArray.0.value"');
            assert.equal(morph.get('myArray.0.value'), 96, 'Структура "myArray.0.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.1.index'), true, 'Объект содержит структуру "myArray.1.index"');
            assert.equal(morph.get('myArray.1.index'), 1, 'Структура "myArray.1.index" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.1.value'), true, 'Объект содержит структуру "myArray.1.value"');
            assert.equal(morph.get('myArray.1.value'), 'text value', 'Структура "myArray.1.value" соответствует ожидаемому значению');

            assert.deepEqual(morph.plain(), source, 'Структура созданного Morphine-объекта соответствует исходной');

        });

        it('Create from path', function () {
            var morph = new Morphine('root.level1.level2.$.value.innerValue', 44);

            assert.equal(morph.has('root.level1.level2.0.value.innerValue'), true, 'Объект содержит структуру "root.level1.level2.0.value.innerValue"');
            assert.equal(morph.get('root.level1.level2.0.value.innerValue'), 44, 'Структура "root.level1.level2.0.value.innerValue" соответствует ожидаемому значению');
        });

    });

    it('isObject', function () {
        var morph = new Morphine();
        assert.equal(morph.isObject(), true, 'Вновь созданая Morphine-сущность является объектом.');
        assert.notEqual(morph.isArray(), true, 'Вновь созданая Morphine-сущность не является массивом.');
    });

    it('isArray', function () {
        var morph = new Morphine('root.$');
        assert.equal(morph.get('root').isArray(), true, 'Вложенный в корень элемент "root" является массивом.');
        assert.notEqual(morph.get('root').isObject(), true, 'Вложенный в корень элемент "root" не является объектом.');
    });

    it('isNull', function () {
        var morph = new Morphine('root', null);
        assert.equal(morph.isNull('root'), true, 'Элемент "root" равен null.');
    });

    it('isUndefined', function () {
        var morph = new Morphine('root', undefined);
        assert.equal(morph.has('root'), true, 'Элемент "root" присутствует в созданном объекте.');
        assert.equal(morph.isUndefined('root'), true, 'Элемент "root" равен undefined.');
    });

    it('isEmpty', function () {
        var morph = new Morphine();
        assert.equal(morph.isEmpty(), true, 'Вновь созданный Morphine-объект является пустым.');
        morph.set('my.path', 'some value');
        assert.notEqual(morph.isEmpty(), true, 'Вновь созданный Morphine-объект не является пустым.');
    });

    it('has', function () {
        var morph = new Morphine('root.level1.level2.$.val', 'some value');
        assert.equal(morph.has('root'), true, 'Объект содержит "root" на текущем уровне.');

        var inner = morph.get('root.level1');
        assert.equal(inner.has('level2'), true, 'Объект содержит "level2" на текущем уровне.');
        assert.notEqual(inner.has('level3'), true, 'Объект не содержит "level3" на текущем уровне.');
        // ===
        assert.equal(morph.has('root.level1.level2'), true, 'Объект содержит вложенную структуру вида "root.level1.level2".');
    });

    describe('merge', function () {

        it('merge with morphine', function () {
            var morph = new Morphine('root.level1.level2.$.val', 'some value');
            var morph2 = new Morphine('root.level1_test', false);

            morph.merge(morph2);

            assert.equal(morph.has('root.level1.level2.0.val'), true, 'Объект содержит базовую структуру, по которой он был создан.');
            assert.equal(morph.has('root.level1_test'), true, 'Объект содержит структуру, которая была добавлена через merge.');
            assert.equal(morph.get('root.level1_test'), false, 'Значение структуры, добавленной через merge соответствует ожидаемому.');

        });

        it('merge with plain object', function () {
            var morph = new Morphine('root.level1.level2.$.val', 'some value');
            var morph2 = {
                root: {
                    level1_test: false
                }
            };

            morph.merge(morph2);

            assert.equal(morph.has('root.level1.level2.0.val'), true, 'Объект содержит базовую структуру, по которой он был создан.');
            assert.equal(morph.has('root.level1_test'), true, 'Объект содержит структуру, которая была добавлена через merge.');
            assert.equal(morph.get('root.level1_test'), false, 'Значение структуры, добавленной через merge соответствует ожидаемому.');

        });
    });

    it('set', function () {
        var morph = new Morphine();

        morph.set('path.part.first', 'is first part');
        assert.equal(morph.has('path.part.first'), true, 'Объект содержит структуру "path.part.first"');
        assert.equal(morph.get('path.part.first'), 'is first part', 'Структура "path.part.first" ссылается на ожидаемое значение');
    });

    // Символический тест. Просто чтобы был, т.к. get и без него повсеместно используется
    it('get', function () {
        var morph = new Morphine();

        morph.set('path.part.first', 'is first part');
        assert.equal(morph.get('path.part.first'), 'is first part', 'Структура "path.part.first" ссылается на ожидаемое значение');
    });

    it('config', function () {
        var morph = new Morphine();

        morph.config({
            separator: "/"
        });

        morph.set('path/part/first', 'path with slash-separate');
        assert.equal(morph.has('path/part/first'), true, 'Разбор строки с кастомным разделителем происходит корректно');
        assert.equal(morph.get('path/part/first'), 'path with slash-separate', 'Распарсили строку с кастомным разделителем и успешно получили ожидаемое значение');
    });

    it('stringify', function () {
        var source = {
            root: {
                level1_test: false,
                arr: [
                    {
                        val1: 'v1',
                        val2: 'v2',
                    },
                    {
                        bool: true
                    },
                    {
                        num: 44
                    }
                ]
            }
        };
        var morph = new Morphine(source);

        var morphStr = morph.stringify();
        var plainStr = JSON.stringify(source);

        assert.equal(morphStr, plainStr, "Morphine-объект корректно преобразован в строку");

    });

    /**
     * Преобразование Morphine-объекта в plain-объект
     */
    //plain
    /**
     * Преобразует текущий экземпляр объекта в массив path-элементов
     */
    //toPaths
    /**
     * Удалит вложенный объект или значение по указанному path
     */
    //remove
    /**
     * Очистит текущий экземпляр объекта
     */
    //clear
    /**
     * Преобразует текущий экземпляр объекта в объект описаный
     * переданным массивом path-элементов
     */
    //buildFromPaths

});
<commit_msg>Проблемы с config-тестом<commit_after>/**
 * Created by KlimMalgin on 21.10.2014.
 */
'use strict';

var assert = require("assert");
require("./Morphine");

describe('Public API tests', function () {
    //var PublicApi = MorphineShareApi.CommonPrototypeMixin;

    describe('Morphine constructor', function () {

        it('Create from object', function () {
            var source = {
                myObject: {
                    start: {
                        value: 'start object value'
                    },
                    end: {
                        value: 'end object value'
                    }
                },
                myArray: [
                    {
                        index: 0,
                        value: 96
                    },
                    {
                        index: 1,
                        value: 'text value'
                    }
                ]
            };
            var morph = new Morphine(source);
            assert.equal(morph.has('myObject.start.value'), true, 'Объект содержит структуру "myObject.start.value"');
            assert.equal(morph.get('myObject.start.value'), 'start object value', 'Структура "myObject.start.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myObject.end.value'), true, 'Объект содержит структуру "myObject.end.value"');
            assert.equal(morph.get('myObject.end.value'), 'end object value', 'Структура "myObject.end.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.0.index'), true, 'Объект содержит структуру "myArray.0.index"');
            assert.equal(morph.get('myArray.0.index'), 0, 'Структура "myArray.0.index" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.0.value'), true, 'Объект содержит структуру "myArray.0.value"');
            assert.equal(morph.get('myArray.0.value'), 96, 'Структура "myArray.0.value" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.1.index'), true, 'Объект содержит структуру "myArray.1.index"');
            assert.equal(morph.get('myArray.1.index'), 1, 'Структура "myArray.1.index" соответствует ожидаемому значению');

            assert.equal(morph.has('myArray.1.value'), true, 'Объект содержит структуру "myArray.1.value"');
            assert.equal(morph.get('myArray.1.value'), 'text value', 'Структура "myArray.1.value" соответствует ожидаемому значению');

            assert.deepEqual(morph.plain(), source, 'Структура созданного Morphine-объекта соответствует исходной');

        });

        it('Create from path', function () {
            var morph = new Morphine('root.level1.level2.$.value.innerValue', 44);

            assert.equal(morph.has('root.level1.level2.0.value.innerValue'), true, 'Объект содержит структуру "root.level1.level2.0.value.innerValue"');
            assert.equal(morph.get('root.level1.level2.0.value.innerValue'), 44, 'Структура "root.level1.level2.0.value.innerValue" соответствует ожидаемому значению');
        });

    });

    it('isObject', function () {
        var morph = new Morphine();
        assert.equal(morph.isObject(), true, 'Вновь созданая Morphine-сущность является объектом.');
        assert.notEqual(morph.isArray(), true, 'Вновь созданая Morphine-сущность не является массивом.');
    });

    it('isArray', function () {
        var morph = new Morphine('root.$');
        assert.equal(morph.get('root').isArray(), true, 'Вложенный в корень элемент "root" является массивом.');
        assert.notEqual(morph.get('root').isObject(), true, 'Вложенный в корень элемент "root" не является объектом.');
    });

    it('isNull', function () {
        var morph = new Morphine('root', null);
        assert.equal(morph.isNull('root'), true, 'Элемент "root" равен null.');
    });

    it('isUndefined', function () {
        var morph = new Morphine('root', undefined);
        assert.equal(morph.has('root'), true, 'Элемент "root" присутствует в созданном объекте.');
        assert.equal(morph.isUndefined('root'), true, 'Элемент "root" равен undefined.');
    });

    it('isEmpty', function () {
        var morph = new Morphine();
        assert.equal(morph.isEmpty(), true, 'Вновь созданный Morphine-объект является пустым.');
        morph.set('my.path', 'some value');
        assert.notEqual(morph.isEmpty(), true, 'Вновь созданный Morphine-объект не является пустым.');
    });

    it('has', function () {
        var morph = new Morphine('root.level1.level2.$.val', 'some value');
        assert.equal(morph.has('root'), true, 'Объект содержит "root" на текущем уровне.');

        var inner = morph.get('root.level1');
        assert.equal(inner.has('level2'), true, 'Объект содержит "level2" на текущем уровне.');
        assert.notEqual(inner.has('level3'), true, 'Объект не содержит "level3" на текущем уровне.');
        // ===
        assert.equal(morph.has('root.level1.level2'), true, 'Объект содержит вложенную структуру вида "root.level1.level2".');
    });

    describe('merge', function () {

        it('merge with morphine', function () {
            var morph = new Morphine('root.level1.level2.$.val', 'some value');
            var morph2 = new Morphine('root.level1_test', false);

            morph.merge(morph2);

            assert.equal(morph.has('root.level1.level2.0.val'), true, 'Объект содержит базовую структуру, по которой он был создан.');
            assert.equal(morph.has('root.level1_test'), true, 'Объект содержит структуру, которая была добавлена через merge.');
            assert.equal(morph.get('root.level1_test'), false, 'Значение структуры, добавленной через merge соответствует ожидаемому.');

        });

        it('merge with plain object', function () {
            var morph = new Morphine('root.level1.level2.$.val', 'some value');
            var morph2 = {
                root: {
                    level1_test: false
                }
            };

            morph.merge(morph2);

            assert.equal(morph.has('root.level1.level2.0.val'), true, 'Объект содержит базовую структуру, по которой он был создан.');
            assert.equal(morph.has('root.level1_test'), true, 'Объект содержит структуру, которая была добавлена через merge.');
            assert.equal(morph.get('root.level1_test'), false, 'Значение структуры, добавленной через merge соответствует ожидаемому.');

        });
    });

    it('set', function () {
        var morph = new Morphine();

        morph.set('path.part.first', 'is first part');
        assert.equal(morph.has('path.part.first'), true, 'Объект содержит структуру "path.part.first"');
        assert.equal(morph.get('path.part.first'), 'is first part', 'Структура "path.part.first" ссылается на ожидаемое значение');
    });

    // Символический тест. Просто чтобы был, т.к. get и без него повсеместно используется
    it('get', function () {
        var morph = new Morphine();

        morph.set('path.part.first', 'is first part');
        assert.equal(morph.get('path.part.first'), 'is first part', 'Структура "path.part.first" ссылается на ожидаемое значение');
    });

    /*it('config', function () {
        var morph = new Morphine();

        morph.config({
            separator: "/"
        });

        morph.set('path/part/first', 'path with slash-separate');
        assert.equal(morph.has('path/part/first'), true, 'Разбор строки с кастомным разделителем происходит корректно');
        assert.equal(morph.get('path/part/first'), 'path with slash-separate', 'Распарсили строку с кастомным разделителем и успешно получили ожидаемое значение');
    });*/

    it('stringify', function () {
        var source = {
            root: {
                level1_test: false,
                arr: [
                    {
                        val1: 'v1',
                        val2: 'v2',
                    },
                    {
                        bool: true
                    },
                    {
                        num: 44
                    }
                ]
            }
        };
        var morph = new Morphine(source);

        var morphStr = morph.stringify();
        var plainStr = JSON.stringify(source);

        assert.equal(morphStr, plainStr, "Morphine-объект корректно преобразован в строку");

    });

    /**
     * Преобразование Morphine-объекта в plain-объект
     */
    //plain
    /**
     * Преобразует текущий экземпляр объекта в массив path-элементов
     */
    //toPaths
    /**
     * Удалит вложенный объект или значение по указанному path
     */
    //remove
    /**
     * Очистит текущий экземпляр объекта
     */
    //clear
    /**
     * Преобразует текущий экземпляр объекта в объект описаный
     * переданным массивом path-элементов
     */
    //buildFromPaths

});
<|endoftext|>


<commit_before>/**
 * Created by orel- on 17/Jan/17.
 */
import express from 'express';
let router = express.Router();
import passport from 'passport';
import GithubPassport from 'passport-github2';
import User from 'models/user';
import {extend} from 'underscore';
import * as jwt from 'jsonwebtoken';

// TODO: Prettify the code

const GithubStrategy = GithubPassport.Strategy;

// Get github credentials
let GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID,
    GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;

// Passport session setup.
//   To support persistent login sessions, Passport needs to be able to
//   serialize users into and deserialize users out of the session.  Typically,
//   this will be as simple as storing the user ID when serializing, and finding
//   the user by ID when deserializing.  However, since this example does not
//   have a database of user records, the complete GitHub profile is serialized
//   and deserialized.
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.find({
        'id': id,
    })
        .exec()
        .then((user) => {
            done(null, user[0]);
        })
        .catch((err) => {
            throw err;
        });
});

// Use the GitHubStrategy within Passport.
//   Strategies in Passport require a `verify` function, which accept
//   credentials (in this case, an accessToken, refreshToken, and GitHub
//   profile), and invoke a callback with a user object.
passport.use(new GithubStrategy({
    'clientID': GITHUB_CLIENT_ID,
    'clientSecret': GITHUB_CLIENT_SECRET,
    'callbackURL': process.env.NODE_ENV === 'production' && 'https://cogs.red/api/v1/auth/github/callback' || 'http://localhost:3000/api/v1/auth/github/callback',
},
function(accessToken, refreshToken, profile, done) {
    User.findOne({
        'id': profile.id,
    })
        .exec()
        .then((user) => {
            if (!user) {
                user = new User(profile);
            } else {
                user = extend(user, profile);
            }

            // generate JWT
            let jwToken = jwt.sign({
                'usr': profile.id,
                'roles': user && user.roles || ['member'],
            }, process.env.JWT_SECRET, {'expiresIn': '100d'});

            user.tokens = {
                'access_token': accessToken,
                'jwt': jwToken,
            };

            return user.save();
        })
        .then((user) => {
            return done(null, user);
        })
        .catch((err) => {
            throw err;
        });
}
));

// GET /auth/github
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  The first step in GitHub authentication will involve redirecting
//   the user to github.com.  After authorization, GitHub will redirect the user
//   back to this application at /auth/github/callback
router.get('/github',
    passport.authenticate('github', { 'scope': [ 'user:email', 'public_repo' ] }),
    (req, res) => {
        // The request will be redirected to GitHub for authentication, so this
        // function will not be called.
    });

// GET /auth/github/callback
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  If authentication fails, the user will be redirected back to the
//   login page.  Otherwise, the primary route function will be called,
//   which, in this example, will redirect the user to the home page.
router.get('/github/callback',
    passport.authenticate('github', { 'failureRedirect': '/login' }),
    (req, res) => {
        // generate JWT for future authorizations
        res.cookie('token', req.user.tokens.jwt, {'maxAge': 60000});
        res.redirect('/');
    });

router.get('/logout', (req, res) => {
    req.logout();
    res.redirect('/');
});

function authorize(req, res, next) {
    let token = req.get('Authorization');
    if (!token && req.get('Service-Token') !== process.env.serviceToken) {
        return res.status(401).send({
            'error': 'Unauthorized',
            'error_details': 'Authorization header not provided',
            'results': {},
        });
    }
    User.findOne({
        'tokens.jwt': token,
    })
        .exec()
        .then((user) => {
            if (!user  && req.get('Service-Token') !== process.env.serviceToken) {
                // override if Service-Token is provided
                throw new Error('Unauthorized');
            }
            req.user = user;
            next();
        })
        .catch((err) => {
            if (err.message === 'Unauthorized') {
                return res.status(401).send({
                    'error': 'Unauthorized',
                    'error_details': 'JWT token invalid',
                    'results': {},
                });
            }
            throw err;
        });
}

export {router, passport, authorize};
<commit_msg>liveserver-exclusive problem debug<commit_after>/**
 * Created by orel- on 17/Jan/17.
 */
import express from 'express';
let router = express.Router();
import passport from 'passport';
import GithubPassport from 'passport-github2';
import User from 'models/user';
import {extend} from 'underscore';
import * as jwt from 'jsonwebtoken';

// TODO: Prettify the code

const GithubStrategy = GithubPassport.Strategy;

// Get github credentials
let GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID,
    GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;

// Passport session setup.
//   To support persistent login sessions, Passport needs to be able to
//   serialize users into and deserialize users out of the session.  Typically,
//   this will be as simple as storing the user ID when serializing, and finding
//   the user by ID when deserializing.  However, since this example does not
//   have a database of user records, the complete GitHub profile is serialized
//   and deserialized.
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.find({
        'id': id,
    })
        .exec()
        .then((user) => {
            done(null, user[0]);
        })
        .catch((err) => {
            throw err;
        });
});

// Use the GitHubStrategy within Passport.
//   Strategies in Passport require a `verify` function, which accept
//   credentials (in this case, an accessToken, refreshToken, and GitHub
//   profile), and invoke a callback with a user object.
passport.use(new GithubStrategy({
    'clientID': GITHUB_CLIENT_ID,
    'clientSecret': GITHUB_CLIENT_SECRET,
    'callbackURL': process.env.NODE_ENV === 'production' && 'https://cogs.red/api/v1/auth/github/callback' || 'http://localhost:3000/api/v1/auth/github/callback',
},
function(accessToken, refreshToken, profile, done) {
    User.findOne({
        'id': profile.id,
    })
        .exec()
        .then((user) => {
            if (!user) {
                user = new User(profile);
            } else {
                user = extend(user, profile);
            }

            // generate JWT
            let jwToken = jwt.sign({
                'usr': profile.id,
                'roles': user && user.roles || ['member'],
            }, process.env.JWT_SECRET, {'expiresIn': '100d'});

            user.tokens = {
                'access_token': accessToken,
                'jwt': jwToken,
            };

            return user.save();
        })
        .then((user) => {
            return done(null, user);
        })
        .catch((err) => {
            throw err;
        });
}
));

// GET /auth/github
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  The first step in GitHub authentication will involve redirecting
//   the user to github.com.  After authorization, GitHub will redirect the user
//   back to this application at /auth/github/callback
router.get('/github',
    passport.authenticate('github', { 'scope': [ 'user:email', 'public_repo' ] }),
    (req, res) => {
        // The request will be redirected to GitHub for authentication, so this
        // function will not be called.
    });

// GET /auth/github/callback
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  If authentication fails, the user will be redirected back to the
//   login page.  Otherwise, the primary route function will be called,
//   which, in this example, will redirect the user to the home page.
router.get('/github/callback',
    passport.authenticate('github', { 'failureRedirect': '/login' }),
    (req, res) => {
        // generate JWT for future authorizations
        res.cookie('token', req.user.tokens.jwt, {'maxAge': 60000});
        res.redirect('/');
    });

router.get('/logout', (req, res) => {
    req.logout();
    res.redirect('/');
});

function authorize(req, res, next) {
    let token = req.get('Authorization');
    console.log('token', token, headers, req.headers);
    if (!token && req.get('Service-Token') !== process.env.serviceToken) {
        return res.status(401).send({
            'error': 'Unauthorized',
            'error_details': 'Authorization header not provided',
            'results': {},
        });
    }
    User.findOne({
        'tokens.jwt': token,
    })
        .exec()
        .then((user) => {
            if (!user  && req.get('Service-Token') !== process.env.serviceToken) {
                // override if Service-Token is provided
                throw new Error('Unauthorized');
            }
            req.user = user;
            next();
        })
        .catch((err) => {
            if (err.message === 'Unauthorized') {
                return res.status(401).send({
                    'error': 'Unauthorized',
                    'error_details': 'JWT token invalid',
                    'results': {},
                });
            }
            throw err;
        });
}

export {router, passport, authorize};
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var auth = require('../middleware/auth');
var router = express.Router();
var passport = require('passport');

// configuration TUD server
var YOUPOWER_REDIRECT_URL = "https://app.civisproject.eu/frontend.html";
var FACEBOOK_CALLBACK_URL = "https://app.civisproject.eu";

//configureation localhost
var YOUPOWER_REDIRECT_URL = "http://localhost:8100/";
var FACEBOOK_CALLBACK_URL = process.env.FACEBOOK_CALLBACK_URL;

var User = require('../models').users;

/**
 * @api {get} /auth/facebook Redirect to Facebook login
 * @apiGroup Facebook Login
 */
router.get('/facebook', passport.authenticate('facebook',
	{scope :['user_friends', 'user_birthday', 'email', 'publish_actions'], session: false}));

/**
 * @api {get} /auth/facebook/callback Callback URL for Facebook login
 * @apiGroup Facebook Login
 *
 * @apiSuccess {Sting} [token] After the Facebook call back, the location is redirected to /#/welcome/ followed by a user token if the  login is successful. The String value can be "fbUnauthorized", "err", or a user token.
 */
router.get('/facebook/callback', passport.authenticate('facebook',
{ failureRedirect: YOUPOWER_REDIRECT_URL + "#/welcome/fbUnauthorized",
  session : false}), function(req, res) {

  auth.newUserToken(req.user, function(err, token) {

    if (err){
      res.redirect(YOUPOWER_REDIRECT_URL + '#/welcome/err');
    }else{
      res.redirect(YOUPOWER_REDIRECT_URL + '#/welcome/' + token);
    }
  });
});

/**
 * @api {get} /auth/facebookc Connecting existing accounts with Facebook
 * @apiGroup Facebook Login
 */
router.get('/facebookc/:id', function(req, res, next) {
  console.log("req.params.id" + req.params.id);

  passport.authenticate('facebook-authz',
	{ callbackURL: FACEBOOK_CALLBACK_URL + '/api/auth/facebook/callbackfb/' + req.params.id,
    scope :['user_friends', 'user_birthday', 'email', 'publish_actions'], session: false
  })(req, res, next);
});

/**
 * @api {get} /auth/facebook/callbackfb Callback URL for Facebook login for connection
 * @apiGroup Facebook Login
 * @apiSuccess {Sting} [res] After the Facebook call back, the location is redirected to /#/app/settings/ followed by "fb" if the login is successful, "fbUnauthorized" otherwise.
 */
router.get('/facebook/callbackfb/:id', function(req, res, next) {

  console.log("req.params.id" + req.params.id)

  passport.authenticate('facebook-authz',
	{callbackURL: FACEBOOK_CALLBACK_URL + '/api/auth/facebook/callbackfb/' + req.params.id,
    failureRedirect: YOUPOWER_REDIRECT_URL + "#/app/settings/main/fbUnauthorized",
    session: false}, function(err, aUser) {

      console.log("user:" + JSON.stringify(aUser, null, 4));

      User.find({_id: req.params.id}, false, null, null, function(err, user) {
        if (err || !user) {
          res.redirect(YOUPOWER_REDIRECT_URL + '#/app/settings/main/fbUnauthorized');
        } else {
          user.facebookId  = aUser.facebookId;
          user.accessToken  = aUser.accessToken;
          user.profile.gender   = aUser.gender;
          user.profile.name   = aUser.name;
          user.profile.dob   = aUser.dob;

          user.markModified('profile.gender');
          user.markModified('profile.name');
          user.markModified('profile.dob');
          user.markModified('facebookId');
          user.markModified('accessToken');
          user.save();

          res.redirect(YOUPOWER_REDIRECT_URL + '#/app/settings/main/')
        }
      });
    }
  )(req, res, next);

});

module.exports = router;
<commit_msg>civis server config<commit_after>'use strict';

var express = require('express');
var auth = require('../middleware/auth');
var router = express.Router();
var passport = require('passport');

// configuration TUD server
var YOUPOWER_REDIRECT_URL = "https://app.civisproject.eu/frontend.html";
var FACEBOOK_CALLBACK_URL = "https://app.civisproject.eu";

//configureation localhost
// var YOUPOWER_REDIRECT_URL = "http://localhost:8100/";
// var FACEBOOK_CALLBACK_URL = process.env.FACEBOOK_CALLBACK_URL;

var User = require('../models').users;

/**
 * @api {get} /auth/facebook Redirect to Facebook login
 * @apiGroup Facebook Login
 */
router.get('/facebook', passport.authenticate('facebook',
	{scope :['user_friends', 'user_birthday', 'email', 'publish_actions'], session: false}));

/**
 * @api {get} /auth/facebook/callback Callback URL for Facebook login
 * @apiGroup Facebook Login
 *
 * @apiSuccess {Sting} [token] After the Facebook call back, the location is redirected to /#/welcome/ followed by a user token if the  login is successful. The String value can be "fbUnauthorized", "err", or a user token.
 */
router.get('/facebook/callback', passport.authenticate('facebook',
{ failureRedirect: YOUPOWER_REDIRECT_URL + "#/welcome/fbUnauthorized",
  session : false}), function(req, res) {

  auth.newUserToken(req.user, function(err, token) {

    if (err){
      res.redirect(YOUPOWER_REDIRECT_URL + '#/welcome/err');
    }else{
      res.redirect(YOUPOWER_REDIRECT_URL + '#/welcome/' + token);
    }
  });
});

/**
 * @api {get} /auth/facebookc Connecting existing accounts with Facebook
 * @apiGroup Facebook Login
 */
router.get('/facebookc/:id', function(req, res, next) {
  console.log("req.params.id" + req.params.id);

  passport.authenticate('facebook-authz',
	{ callbackURL: FACEBOOK_CALLBACK_URL + '/api/auth/facebook/callbackfb/' + req.params.id,
    scope :['user_friends', 'user_birthday', 'email', 'publish_actions'], session: false
  })(req, res, next);
});

/**
 * @api {get} /auth/facebook/callbackfb Callback URL for Facebook login for connection
 * @apiGroup Facebook Login
 * @apiSuccess {Sting} [res] After the Facebook call back, the location is redirected to /#/app/settings/ followed by "fb" if the login is successful, "fbUnauthorized" otherwise.
 */
router.get('/facebook/callbackfb/:id', function(req, res, next) {

  console.log("req.params.id" + req.params.id)

  passport.authenticate('facebook-authz',
	{callbackURL: FACEBOOK_CALLBACK_URL + '/api/auth/facebook/callbackfb/' + req.params.id,
    failureRedirect: YOUPOWER_REDIRECT_URL + "#/app/settings/main/fbUnauthorized",
    session: false}, function(err, aUser) {

      console.log("user:" + JSON.stringify(aUser, null, 4));

      User.find({_id: req.params.id}, false, null, null, function(err, user) {
        if (err || !user) {
          res.redirect(YOUPOWER_REDIRECT_URL + '#/app/settings/main/fbUnauthorized');
        } else {
          user.facebookId  = aUser.facebookId;
          user.accessToken  = aUser.accessToken;
          user.profile.gender   = aUser.gender;
          user.profile.name   = aUser.name;
          user.profile.dob   = aUser.dob;

          user.markModified('profile.gender');
          user.markModified('profile.name');
          user.markModified('profile.dob');
          user.markModified('facebookId');
          user.markModified('accessToken');
          user.save();

          res.redirect(YOUPOWER_REDIRECT_URL + '#/app/settings/main/')
        }
      });
    }
  )(req, res, next);

});

module.exports = router;
<|endoftext|>


<commit_before>var dataset;

var settings = {
    w: 600,
    h: 600,
    wAxeY: 100,
    hAxeX: 200,
    containerId: "#chart-container",
    sorted: false,
    selectedYear: 0
};

var conf;

function createChart(settings) {
    //Create svg element
    d3.select(settings.containerId).append("svg")
        .attr("width", settings.w).attr("height", settings.h)
        .attr("id", "chart");
    //    .attr("viewBox", "0 0 "+w+ " "+h)
    //    .attr("preserveAspectRatio", "xMinYMin");

    //Define tooltip for hover-over info windows
    /*var div = d3.select("body").append("div")
        .attr("class", "tooltip")
        .style("opacity", 0);
    */
}

//Define bar chart function
function barChart(dataset, settings){
    //Set width and height as fixed variables
    var w = settings.w;
    var h = settings.h;
    var wAxeY = settings.wAxeY;
    var hAxeX = settings.hAxeX;
    var displayValue = settings.displayValue;

    var data = dataset[settings.selectedYear]["regions"].sort(sortChoice(settings.sorted));

    var yDomain = d3.extent(data, function(d){ return d[displayValue] });

    var yRangeBegin = 0;
    if(yDomain[0] >= 0){
        yRangeBegin = h - hAxeX;
        yDomain[0] = 0;
    }else {
        yRangeBegin = h;
    }
    //Scale function for axes and radius
    var yScale = d3.scalePow()
        .domain(yDomain)
        .range([yRangeBegin, 0]);

    var xScale = d3.scaleBand()
            .rangeRound([wAxeY, w])
            .padding(0.1)
            .domain(data.map(function(d){ return d.name;}));

    //Create y axis
    var yAxis = d3.axisLeft().scale(yScale);

    var xAxis = d3.axisTop().scale(xScale);

    //Define key function
    var key = function(d){return d.name};

    //Initialize state of chart according to drop down menu

    var svg = d3.select(settings.containerId).select("#chart");
    //Create bar chart

    var barPositionPipeline = function(selection) {
        selection.attr("class", function(d){return d[displayValue] < 0 ? "negative" : "positive";})
            .attr("x", function(d){
                    return xScale(d.name);
                })

            .attr("y", function(d){
                    return yScale(Math.max(0, d[displayValue]));
                })
            .attr("width", xScale.bandwidth())
            // .transition()
            // .duration(500)
            .attr("height", function(d){
                    return Math.abs(yScale(d[displayValue]) - yScale(0));
            });
    };

    svg.selectAll("rect")
        .data(data, key)
        .enter()
        .append("rect")
        .call(barPositionPipeline);

    svg.selectAll("rect")
        .data(data, key)
        .call(barPositionPipeline);

    var yAxisDom = svg.select(".y-axis");
    if (yAxisDom.size()) {
        yAxisDom.call(yAxis)
    } else {
        //Add y-axis
        svg.append("g")
            .attr("class", "y-axis")
            .attr("transform", "translate("+ wAxeY + ",0)")
            .call(yAxis);
    }

    var xAxisDom = svg.select(".x-axis");
    var labels;
    if (xAxisDom.size()) {
        labels = xAxisDom
            .attr("transform", "translate(0, "+ yScale(0) + ")")
            .call(xAxis)
            .selectAll("text");
    } else {
        labels = svg.append("g")
            .attr("class", "x-axis")
            .attr("transform", "translate(0, "+ yScale(0) + ")")
            .call(xAxis)
            .selectAll("text")
            .style("alignment-baseline", "middle")
            .attr("transform", "rotate(-90)")
            .attr("dy", 10);
    }

    function isPositive(i) {
        return data[i][displayValue]>= 0.0
    }

    labels.filter(function(d, i) { return isPositive(i)})
        .style("text-anchor", "end")
        .attr("dx", -10);

    labels.filter(function(d, i) { return !isPositive(i); })
        .style("text-anchor", "start")
        .attr("dx", 10);

    //Function to sort data when sort box is checked
    function sortChoice(sorted){
        if (sorted) {
            return function(a,b){return b[displayValue] - a[displayValue];};
        } else {
            return function(a,b){return d3.ascending(a.name, b.name);};
        }
    }
}

//Load data and call bar chart function
d3.json("diff.json", function(error,data){
    dataset = data;
    if(error){
        console.log(error);
    }else{
        conf = $.extend({}, settings);
        conf.displayValue = d3.select('input[name="choice"]:checked').attr('value');

        createChart(conf);
        barChart(data, conf);
    }

    d3.select("#year")
        .selectAll('option')
        .data(data)
        .enter()
        .append('option')
        .attr('value', function(d, i) {return i})
        .text(function(d) {return d.year});

    $('input[name="choice"]').on('change', function() {
        conf.displayValue = $(this).attr('value');
        barChart(data, conf);
    });

    $('.checkbox').on('change', function() {
        conf.sorted = $(this).is(':checked');
        barChart(data, conf);
    });

    $('#year').on('change', function() {
        conf.selectedYear = $(this).val();
        barChart(data, conf);
    });
});
<commit_msg>[Chart] Added animation<commit_after>var dataset;

var settings = {
    w: 600,
    h: 600,
    wAxeY: 100,
    hAxeX: 200,
    containerId: "#chart-container",
    sorted: false,
    selectedYear: 0,
    duration: 500
};

var conf;

function createChart(settings) {
    //Create svg element
    d3.select(settings.containerId).append("svg")
        .attr("width", settings.w).attr("height", settings.h)
        .attr("id", "chart");
    //    .attr("viewBox", "0 0 "+w+ " "+h)
    //    .attr("preserveAspectRatio", "xMinYMin");

    //Define tooltip for hover-over info windows
    /*var div = d3.select("body").append("div")
        .attr("class", "tooltip")
        .style("opacity", 0);
    */
}

//Define bar chart function
function barChart(dataset, settings){
    //Set width and height as fixed variables
    var w = settings.w;
    var h = settings.h;
    var wAxeY = settings.wAxeY;
    var hAxeX = settings.hAxeX;
    var displayValue = settings.displayValue;

    var data = dataset[settings.selectedYear]["regions"].sort(sortChoice(settings.sorted));

    var yDomain = d3.extent(data, function(d){ return d[displayValue] });

    var yRangeBegin = 0;
    if(yDomain[0] >= 0){
        yRangeBegin = h - hAxeX;
        yDomain[0] = 0;
    }else {
        yRangeBegin = h;
    }
    //Scale function for axes and radius
    var yScale = d3.scalePow()
        .domain(yDomain)
        .range([yRangeBegin, 0]);

    var xScale = d3.scaleBand()
            .rangeRound([wAxeY, w])
            .padding(0.1)
            .domain(data.map(function(d){ return d.name;}));

    //Create y axis
    var yAxis = d3.axisLeft().scale(yScale);

    var xAxis = d3.axisTop().scale(xScale);

    //Define key function
    var key = function(d){return d.name};

    //Initialize state of chart according to drop down menu

    var svg = d3.select(settings.containerId).select("#chart");
    //Create bar chart

    var barPositionPipeline = function(selection) {
        selection.attr("class", function(d){return d[displayValue] < 0 ? "negative" : "positive";})
            .attr("x", function(d){
                    return xScale(d.name);
                })

            .attr("y", function(d){
                    return yScale(Math.max(0, d[displayValue]));
                })
            .attr("width", xScale.bandwidth())
            .attr("height", function(d){
                    return Math.abs(yScale(d[displayValue]) - yScale(0));
            });
    };

    svg.selectAll("rect")
        .data(data, key)
        .enter()
        .append("rect")
        .call(barPositionPipeline);

    svg.selectAll("rect")
        .data(data, key)
        .transition()
        .duration(settings.duration)
        .call(barPositionPipeline);

    var yAxisDom = svg.select(".y-axis");
    if (yAxisDom.size()) {
        yAxisDom.call(yAxis)
    } else {
        //Add y-axis
        svg.append("g")
            .attr("class", "y-axis")
            .attr("transform", "translate("+ wAxeY + ",0)")
            .call(yAxis);
    }

    var xAxisDom = svg.select(".x-axis");
    var labels;
    if (xAxisDom.size()) {
        labels = xAxisDom
            .attr("transform", "translate(0, "+ yScale(0) + ")")
            .transition()
            .duration(settings.duration)
            .call(xAxis)
            .selectAll("text");
    } else {
        labels = svg.append("g")
            .attr("class", "x-axis")
            .attr("transform", "translate(0, "+ yScale(0) + ")")
            .call(xAxis)
            .selectAll("text")
            .style("alignment-baseline", "middle")
            .attr("transform", "rotate(-90)")
            .attr("dy", 10);
    }

    function isPositive(i) {
        return data[i][displayValue]>= 0.0
    }

    labels.filter(function(d, i) { return isPositive(i)})
        .style("text-anchor", "end")
        .attr("dx", -10);

    labels.filter(function(d, i) { return !isPositive(i); })
        .style("text-anchor", "start")
        .attr("dx", 10);

    //Function to sort data when sort box is checked
    function sortChoice(sorted){
        if (sorted) {
            return function(a,b){return b[displayValue] - a[displayValue];};
        } else {
            return function(a,b){return d3.ascending(a.name, b.name);};
        }
    }
}

//Load data and call bar chart function
d3.json("diff.json", function(error,data){
    dataset = data;
    if(error){
        console.log(error);
    }else{
        conf = $.extend({}, settings);
        conf.displayValue = d3.select('input[name="choice"]:checked').attr('value');

        createChart(conf);
        barChart(data, conf);
    }

    d3.select("#year")
        .selectAll('option')
        .data(data)
        .enter()
        .append('option')
        .attr('value', function(d, i) {return i})
        .text(function(d) {return d.year});

    $('input[name="choice"]').on('change', function() {
        conf.displayValue = $(this).attr('value');
        barChart(data, conf);
    });

    $('.checkbox').on('change', function() {
        conf.sorted = $(this).is(':checked');
        barChart(data, conf);
    });

    $('#year').on('change', function() {
        conf.selectedYear = $(this).val();
        barChart(data, conf);
    });
});
<|endoftext|>


<commit_before>const perf = require('./performance');

// import default stylesheet with variables
require('font-awesome/css/font-awesome.css');
require('../styles/application.scss');

function onDomContentLoaded(callback) {
  if (document.readyState !== 'loading') {
    callback();
  } else {
    document.addEventListener('DOMContentLoaded', callback);
  }
}

function main() {
  perf.start('main()');
  const Mastodon = require('mastodon/containers/mastodon').default;
  const React = require('react');
  const ReactDOM = require('react-dom');

  require.context('../images/', true);

  onDomContentLoaded(() => {
    const mountNode = document.getElementById('mastodon');
    const props = JSON.parse(mountNode.getAttribute('data-props'));

    ReactDOM.render(<Mastodon {...props} />, mountNode);
    perf.stop('main()');
  });
}

export default main;
<commit_msg>Import custom.scss instead of application.scsss<commit_after>const perf = require('./performance');

// import default stylesheet with variables
require('font-awesome/css/font-awesome.css');
require('../styles/custom.scss');

function onDomContentLoaded(callback) {
  if (document.readyState !== 'loading') {
    callback();
  } else {
    document.addEventListener('DOMContentLoaded', callback);
  }
}

function main() {
  perf.start('main()');
  const Mastodon = require('mastodon/containers/mastodon').default;
  const React = require('react');
  const ReactDOM = require('react-dom');

  require.context('../images/', true);

  onDomContentLoaded(() => {
    const mountNode = document.getElementById('mastodon');
    const props = JSON.parse(mountNode.getAttribute('data-props'));

    ReactDOM.render(<Mastodon {...props} />, mountNode);
    perf.stop('main()');
  });
}

export default main;
<|endoftext|>


<commit_before>'use strict';

angular.module('f9-webrtc')

    .controller('ContactsCtrl', ['$scope', '$timeout', 'ContactsService', function($scope, $timeout, ContactsService) {
        $scope.contacts = ContactsService.onlineUsers;

        $scope.title = ' `s Contacts';

        // watch the service for updates to the user status
        $scope.$watch(ContactsService.getUsers, function(newValue, oldValue, scope) {
            console.log('\n** !Contacts Updated ', newValue);
            $timeout(function() {
                $scope.currentUser = newValue.currentUser;

               // $scope.title = $scope.currentUser + ' `s Contacts';
            }, 20);
        });

    }]);<commit_msg>Contacts UI - Trello #56-contacts-ui<commit_after>'use strict';

angular.module('f9-webrtc')

    .controller('ContactsCtrl', ['$scope', '$timeout', 'ContactsService', function($scope, $timeout, ContactsService) {
        $scope.contacts = ContactsService.onlineUsers;

        // watch the service for updates to the user status
        $scope.$watch(ContactsService.getUsers, function(newValue, oldValue, scope) {
            console.log('\n** !Contacts Updated ', newValue);
            $timeout(function() {
                $scope.currentUser = newValue.currentUser;
            }, 20);
        });

    }]);
<|endoftext|>


<commit_before>import randomInt from 'random-int';
import assetsManager from '../managers/assetsManager';
import screensManager from '../managers/screensManager';
import serverManager from '../managers/serverManager';
import dataManager from '../managers/dataManager';
import Gui from '../display/Gui';
import Btn from '../display/Btn';

export default class EndScreen extends createjs.Container {
  constructor(width) {
    super();

    this.bg = new createjs.Bitmap(assetsManager.getResult('start'));
    this.gui = new Gui(width);

    this.maxScore = new createjs.Text(`Рекорд: ${dataManager.maxScore} м`, '25px Guerilla', '#000');
    this.maxScore.textAlign = 'center';
    this.maxScore.x = width / 2;
    this.maxScore.y = 40;

    this.score = new createjs.Text(`Результат: ${dataManager.score} м`, '40px Guerilla', '#000');
    this.score.textAlign = 'center';
    this.score.x = width / 2;
    this.score.y = 150;

    this.replayBtn = new Btn('Еще раз');
    this.replayBtn.x = width / 2;
    this.replayBtn.y = 350;

    this.shareBtn = new Btn('Поделиться', 'orange');
    this.shareBtn.x = width / 2;
    this.shareBtn.y = 440;

    this.addChild(this.bg, this.gui, this.maxScore, this.score, this.replayBtn, this.shareBtn);

    if (dataManager.score > dataManager.maxScore) {
      this.maxScore.text = `Прошлый рекорд: ${dataManager.maxScore} м`;
      dataManager.maxScore = dataManager.score;
      serverManager.set('maxScore', dataManager.maxScore);
      this.score.text = `Новый рекорд: ${dataManager.maxScore} м!`;

      serverManager.get('ratingTable', 1).then(recalcRatingTable);
    }

    if (dataManager.gameType === 'pvp') {
      this.pvpText = new createjs.Text('', '25px Guerilla', '#000');
      this.pvpText.textAlign = 'center';
      this.pvpText.x = width / 2;
      this.pvpText.y = 230;
      this.addChild(this.pvpText);

      if (dataManager.win) {
        this.pvpText.text += `${dataManager.enemy.name} был${dataManager.enemy.sex !== 2 ? 'а' : ''} повержен${dataManager.enemy.sex !== 2 ? 'а' : ''}`;
      } else {
        this.pvpText.text += `${dataManager.enemy.name} поверг${dataManager.enemy.sex !== 2 ? 'ла' : ''} Вас`;
      }
    }

    const range = dataManager.fields[dataManager.gameMode][dataManager.pos];
    const field = `pvp${randomInt(range[0], range[1])}`;
    const record = {
      user: dataManager.user,
      spikes: dataManager.spikes,
      actions: dataManager.actions,
    };

    serverManager.get(field, 1).then(r => {
      console.warn(field);
      console.warn(record);
      console.warn(r);
      console.warn(r.spikes.length * 0.5 < record.spikes.length);
      if (r.spikes.length * 0.5 < record.spikes.length &&
          JSON.stringify(record).length < 4096) {
        serverManager.set(field, record, 1);
      }
    });

    this.bindEvents();
  }
  bindEvents() {
    this.replayBtn.addEventListener('click', replay);
    this.shareBtn.addEventListener('click', share);

    this.onKeyDown = e => {
      if (e.keyCode === 32) {
        replay();
        e.preventDefault();
      }
    };
    window.addEventListener('keydown', this.onKeyDown);
  }
  destroy() {
    window.removeEventListener('keydown', this.onKeyDown);
  }
}

function replay() {
  switch (dataManager.gameType) {
    case 'single':
      screensManager.change('MainScreen');
      break;
    case 'pvp':
      screensManager.change('PVPScreen');
      break;
  }
}

function share () {
  let message = '';
  switch (dataManager.gameType) {
    case 'single':
      message = `Я пролетел${dataManager.user.sex !== 2 ? 'а' : ''} ${dataManager.score} м в игре Flappy Monster!`;
      if (dataManager.score === dataManager.maxScore) {
        message += '\nЭто мой новый рекорд! ';
      }
      message += '\nА сколько сможешь ты?';
      break;
    case 'pvp':
      if (dataManager.win) {
        message += `${dataManager.enemy.name} был${dataManager.enemy.sex !== 2 ? 'а' : ''} повержен${dataManager.enemy.sex !== 2 ? 'а' : ''} мной в игре Flappy Monster!`;
      } else {
        message += `${dataManager.enemy.name} поверг${dataManager.enemy.sex !== 2 ? 'ла' : ''} меня в игре Flappy Monster,
                   ну ничего, еще увидимся...`;
      }
      if (dataManager.score === dataManager.maxScore) {
        message += `\nМой новый рекорд ${dataManager.score} м!`;
      }
      break;
  }
  serverManager.share(message, dataManager.gameType);
}

function recalcRatingTable(ratingTable) {
  if (ratingTable[ratingTable.length - 1].score >= dataManager.maxScore) {
    return;
  }

  const userRating = ratingTable.find(el => el.id === dataManager.user.id);

  if (userRating) {
    userRating.score = dataManager.maxScore;
  } else {
    const newRating = {
      id: dataManager.user.id,
      name: dataManager.user.name,
      score: dataManager.maxScore,
    };
    if (ratingTable.length < 10) {
      ratingTable.push(newRating);
    } else {
      ratingTable[ratingTable.length - 1] = newRating;
    }
  }

  ratingTable.sort((a, b) => b.score - a.score);
  serverManager.set('ratingTable', ratingTable, 1);
}
<commit_msg>rewrite empty record<commit_after>import randomInt from 'random-int';
import assetsManager from '../managers/assetsManager';
import screensManager from '../managers/screensManager';
import serverManager from '../managers/serverManager';
import dataManager from '../managers/dataManager';
import Gui from '../display/Gui';
import Btn from '../display/Btn';

export default class EndScreen extends createjs.Container {
  constructor(width) {
    super();

    this.bg = new createjs.Bitmap(assetsManager.getResult('start'));
    this.gui = new Gui(width);

    this.maxScore = new createjs.Text(`Рекорд: ${dataManager.maxScore} м`, '25px Guerilla', '#000');
    this.maxScore.textAlign = 'center';
    this.maxScore.x = width / 2;
    this.maxScore.y = 40;

    this.score = new createjs.Text(`Результат: ${dataManager.score} м`, '40px Guerilla', '#000');
    this.score.textAlign = 'center';
    this.score.x = width / 2;
    this.score.y = 150;

    this.replayBtn = new Btn('Еще раз');
    this.replayBtn.x = width / 2;
    this.replayBtn.y = 350;

    this.shareBtn = new Btn('Поделиться', 'orange');
    this.shareBtn.x = width / 2;
    this.shareBtn.y = 440;

    this.addChild(this.bg, this.gui, this.maxScore, this.score, this.replayBtn, this.shareBtn);

    if (dataManager.score > dataManager.maxScore) {
      this.maxScore.text = `Прошлый рекорд: ${dataManager.maxScore} м`;
      dataManager.maxScore = dataManager.score;
      serverManager.set('maxScore', dataManager.maxScore);
      this.score.text = `Новый рекорд: ${dataManager.maxScore} м!`;

      serverManager.get('ratingTable', 1).then(recalcRatingTable);
    }

    if (dataManager.gameType === 'pvp') {
      this.pvpText = new createjs.Text('', '25px Guerilla', '#000');
      this.pvpText.textAlign = 'center';
      this.pvpText.x = width / 2;
      this.pvpText.y = 230;
      this.addChild(this.pvpText);

      if (dataManager.win) {
        this.pvpText.text += `${dataManager.enemy.name} был${dataManager.enemy.sex !== 2 ? 'а' : ''} повержен${dataManager.enemy.sex !== 2 ? 'а' : ''}`;
      } else {
        this.pvpText.text += `${dataManager.enemy.name} поверг${dataManager.enemy.sex !== 2 ? 'ла' : ''} Вас`;
      }
    }

    const range = dataManager.fields[dataManager.gameMode][dataManager.pos];
    const field = `pvp${randomInt(range[0], range[1])}`;
    const record = {
      user: dataManager.user,
      spikes: dataManager.spikes,
      actions: dataManager.actions,
    };

    serverManager.get(field, 1).then(r => {
      console.warn(field);
      console.warn(record);
      console.warn(r);

      if ((!r || r.spikes.length * 0.5 < record.spikes.length) &&
          JSON.stringify(record).length < 4096) {
        console.warn(true);
        serverManager.set(field, record, 1);
      }
    });

    this.bindEvents();
  }
  bindEvents() {
    this.replayBtn.addEventListener('click', replay);
    this.shareBtn.addEventListener('click', share);

    this.onKeyDown = e => {
      if (e.keyCode === 32) {
        replay();
        e.preventDefault();
      }
    };
    window.addEventListener('keydown', this.onKeyDown);
  }
  destroy() {
    window.removeEventListener('keydown', this.onKeyDown);
  }
}

function replay() {
  switch (dataManager.gameType) {
    case 'single':
      screensManager.change('MainScreen');
      break;
    case 'pvp':
      screensManager.change('PVPScreen');
      break;
  }
}

function share () {
  let message = '';
  switch (dataManager.gameType) {
    case 'single':
      message = `Я пролетел${dataManager.user.sex !== 2 ? 'а' : ''} ${dataManager.score} м в игре Flappy Monster!`;
      if (dataManager.score === dataManager.maxScore) {
        message += '\nЭто мой новый рекорд! ';
      }
      message += '\nА сколько сможешь ты?';
      break;
    case 'pvp':
      if (dataManager.win) {
        message += `${dataManager.enemy.name} был${dataManager.enemy.sex !== 2 ? 'а' : ''} повержен${dataManager.enemy.sex !== 2 ? 'а' : ''} мной в игре Flappy Monster!`;
      } else {
        message += `${dataManager.enemy.name} поверг${dataManager.enemy.sex !== 2 ? 'ла' : ''} меня в игре Flappy Monster,
                   ну ничего, еще увидимся...`;
      }
      if (dataManager.score === dataManager.maxScore) {
        message += `\nМой новый рекорд ${dataManager.score} м!`;
      }
      break;
  }
  serverManager.share(message, dataManager.gameType);
}

function recalcRatingTable(ratingTable) {
  if (ratingTable[ratingTable.length - 1].score >= dataManager.maxScore) {
    return;
  }

  const userRating = ratingTable.find(el => el.id === dataManager.user.id);

  if (userRating) {
    userRating.score = dataManager.maxScore;
  } else {
    const newRating = {
      id: dataManager.user.id,
      name: dataManager.user.name,
      score: dataManager.maxScore,
    };
    if (ratingTable.length < 10) {
      ratingTable.push(newRating);
    } else {
      ratingTable[ratingTable.length - 1] = newRating;
    }
  }

  ratingTable.sort((a, b) => b.score - a.score);
  serverManager.set('ratingTable', ratingTable, 1);
}
<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const WebpackChain = require('webpack-chain')
const { VueLoaderPlugin } = require('vue-loader')

const WebpackProgressPlugin = require('./plugin.progress')
const BootDefaultExport = require('./plugin.boot-default-export')
const parseBuildEnv = require('../helpers/parse-build-env')

const appPaths = require('../app-paths')
const injectStyleRules = require('./inject.style-rules')
const { webpackNames } = require('./symbols')

function getDependenciesRegex (list) {
  const deps = list.map(dep => {
    if (typeof dep === 'string') {
      return path.join('node_modules', dep, '/')
        .replace(/\\/g, '[\\\\/]') // windows support
    }
    else if (dep instanceof RegExp) {
      return dep.source
    }
  })

  return new RegExp(deps.join('|'))
}

function getRootDefines (rootDefines, configName) {
  if (configName === webpackNames.ssr.serverSide) {
    return { ...rootDefines, __QUASAR_SSR_SERVER__: true }
  }

  if (configName === webpackNames.ssr.clientSide) {
    return { ...rootDefines, __QUASAR_SSR_CLIENT__: true }
  }

  return rootDefines
}

module.exports = function (cfg, configName) {
  const chain = new WebpackChain()

  const needsHash = !cfg.ctx.dev && !['electron', 'cordova', 'capacitor', 'bex'].includes(cfg.ctx.modeName)
  const fileHash = needsHash ? '.[contenthash:8]' : ''
  const chunkHash = needsHash ? '.[chunkhash:8]' : ''
  const resolveModules = [
    'node_modules',
    appPaths.resolve.app('node_modules'),
    appPaths.resolve.cli('node_modules')
  ]

  chain.entry('app').add(appPaths.resolve.app('.quasar/client-entry.js'))
  chain.mode(cfg.ctx.dev ? 'development' : 'production')
  chain.devtool(cfg.build.sourceMap ? cfg.build.devtool : false)

  if (cfg.ctx.prod || cfg.ctx.mode.ssr) {
    chain.output
      .path(
        cfg.ctx.mode.ssr
          ? path.join(cfg.build.distDir, 'www')
          : cfg.build.distDir
      )
      .publicPath(cfg.build.publicPath)
      .filename(`js/[name]${fileHash}.js`)
      .chunkFilename(`js/[name]${chunkHash}.js`)
  }

  chain.resolve.symlinks(false)

  chain.resolve.extensions
    .merge(
      cfg.supportTS !== false
        ? [ '.mjs', '.ts', '.js', '.vue', '.json', '.wasm' ]
        : [ '.mjs', '.js', '.vue', '.json', '.wasm' ]
    )

  chain.resolve.modules
    .merge(resolveModules)

  chain.resolve.alias
    .merge({
      src: appPaths.srcDir,
      app: appPaths.appDir,
      components: appPaths.resolve.src(`components`),
      layouts: appPaths.resolve.src(`layouts`),
      pages: appPaths.resolve.src(`pages`),
      assets: appPaths.resolve.src(`assets`),
      boot: appPaths.resolve.src(`boot`),

      'src-bex': appPaths.bexDir // needed for app/templates
    })

  const vueFile = configName === webpackNames.ssr.serverSide
    ? (cfg.ctx.prod ? 'vue.cjs.prod.js' : 'vue.cjs.js')
    : (
      cfg.build.vueCompiler
        ? 'vue.esm-bundler.js'
        : 'vue.runtime.esm-bundler.js'
    )

  chain.resolve.alias.set('vue$', 'vue/dist/' + vueFile)

  const vueI18nFile = configName === webpackNames.ssr.serverSide
    ? (cfg.ctx.prod ? 'vue-i18n.cjs.prod.js' : 'vue-i18n.cjs.js')
    : 'vue-i18n.esm-bundler.js'

  chain.resolve.alias.set('vue-i18n$', 'vue-i18n/dist/' + vueI18nFile)

  chain.resolveLoader.modules
    .merge(resolveModules)

  chain.module.noParse(
    /^(vue|vue-router|vuex|vuex-router-sync|@quasar[\\/]extras|quasar[\\/]dist)$/
  )

  const vueRule = chain.module.rule('vue')
    .test(/\.vue$/)

  vueRule.use('vue-auto-import-quasar')
    .loader(path.join(__dirname, 'loader.vue.auto-import-quasar.js'))
    .options({
      autoImportComponentCase: cfg.framework.autoImportComponentCase,
      isServerBuild: configName === webpackNames.ssr.serverSide
    })

  vueRule.use('vue-loader')
    .loader('vue-loader')
    .options(
      merge(
        cfg.build.vueLoaderOptions,
        {
          isServerBuild: configName === webpackNames.ssr.serverSide,
          compilerOptions: configName === webpackNames.ssr.serverSide
            ? { directiveTransforms: cfg.ssr.directiveTransforms, ssr: true }
            : {}
        }
      )
    )

  if (configName !== webpackNames.ssr.serverSide) {
    chain.module.rule('js-transform-quasar-imports')
      .test(/\.(t|j)sx?$/)
      .use('transform-quasar-imports')
        .loader(path.join(__dirname, 'loader.js.transform-quasar-imports.js'))
  }

  if (cfg.build.transpile === true) {
    const nodeModulesRegex = /[\\/]node_modules[\\/]/
    const exceptionsRegex = getDependenciesRegex(
      [ /\.vue\.js$/, configName === webpackNames.ssr.serverSide ? 'quasar/src' : 'quasar', '@babel/runtime' ]
        .concat(cfg.build.transpileDependencies)
    )

    chain.module.rule('babel')
      .test(/\.js$/)
      .exclude
        .add(filepath => (
          // Transpile the exceptions:
          exceptionsRegex.test(filepath) === false &&
          // Don't transpile anything else in node_modules:
          nodeModulesRegex.test(filepath)
        ))
        .end()
      .use('babel-loader')
        .loader('babel-loader')
          .options({
            compact: false,
            extends: appPaths.resolve.app('babel.config.js')
          })
  }

  if (cfg.supportTS !== false) {
    chain.module
      .rule('typescript')
      .test(/\.ts$/)
      .use('ts-loader')
        .loader('ts-loader')
        .options({
          // custom config is merged if present, but vue setup and type checking disable are always applied
          ...(cfg.supportTS.tsLoaderConfig || {}),
          appendTsSuffixTo: [ /\.vue$/ ],
          // Type checking is handled by fork-ts-checker-webpack-plugin
          transpileOnly: true
        })

    const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
    chain
      .plugin('ts-checker')
      // https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options
      .use(ForkTsCheckerWebpackPlugin, [
        // custom config is merged if present, but vue option is always enabled
        merge({}, cfg.supportTS.tsCheckerConfig || {}, {
          typescript: {
            extensions: {
              vue: {
                enabled: true,
                compiler: '@vue/compiler-sfc'
              }
            }
          }
        })
      ])
  }

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('images')
    .test(/\.(png|jpe?g|gif|svg|webp|avif|ico)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 10000,
        name: `img/[name]${fileHash}.[ext]`
      })

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('fonts')
    .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 10000,
        name: `fonts/[name]${fileHash}.[ext]`
      })

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('media')
    .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 10000,
        name: `media/[name]${fileHash}.[ext]`
      })

  injectStyleRules(chain, {
    isServerBuild: configName === webpackNames.ssr.serverSide,
    rtl: cfg.build.rtl,
    sourceMap: cfg.build.sourceMap,
    extract: cfg.build.extractCSS,
    minify: cfg.build.minify,
    stylusLoaderOptions: cfg.build.stylusLoaderOptions,
    sassLoaderOptions: cfg.build.sassLoaderOptions,
    scssLoaderOptions: cfg.build.scssLoaderOptions,
    lessLoaderOptions: cfg.build.lessLoaderOptions
  })

  chain.module // fixes https://github.com/graphql/graphql-js/issues/1272
    .rule('mjs')
    .test(/\.mjs$/)
    .type('javascript/auto')
    .include
      .add(/[\\/]node_modules[\\/]/)

  chain.plugin('vue-loader')
    .use(VueLoaderPlugin)

  chain.plugin('define')
    .use(webpack.DefinePlugin, [
      parseBuildEnv(cfg.build.env, getRootDefines(cfg.__rootDefines, configName))
    ])

  if (cfg.ctx.dev && configName !== webpackNames.ssr.serverSide && cfg.ctx.mode.pwa && cfg.pwa.workboxPluginMode === 'InjectManifest') {
    // need to place it here before the status plugin
    const CustomSwWarningPlugin = require('./pwa/plugin.custom-sw-warning')
    chain.plugin('custom-sw-warning')
      .use(CustomSwWarningPlugin)
  }

  chain.plugin('progress')
    .use(WebpackProgressPlugin, [{ name: configName, cfg }])

  chain.plugin('boot-default-export')
    .use(BootDefaultExport)

  chain.performance
    .hints(false)
    .maxAssetSize(500000)

  if (configName !== webpackNames.ssr.serverSide && cfg.vendor.disable !== true) {
    const { add, remove } = cfg.vendor
    const regex = /[\\/]node_modules[\\/]/

    chain.optimization.splitChunks({
      cacheGroups: {
        defaultVendors: {
          name: 'vendor',
          chunks: 'all',
          priority: -10,
          // a module is extracted into the vendor chunk if...
          test: add !== void 0 || remove !== void 0
            ? module => {
              if (module.resource) {
                if (remove !== void 0 && remove.test(module.resource)) { return false }
                if (add !== void 0 && add.test(module.resource)) { return true }
              }
              return regex.test(module.resource)
            }
            : regex
        },
        common: {
          name: `chunk-common`,
          minChunks: 2,
          priority: -20,
          chunks: 'all',
          reuseExistingChunk: true
        }
      }
    })
  }

  // extract css into its own file
  if (configName !== webpackNames.ssr.serverSide && cfg.build.extractCSS) {
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')

    chain.plugin('mini-css-extract')
      .use(MiniCssExtractPlugin, [{
        filename: `css/[name]${fileHash}.css`
      }])
  }

  if (cfg.ctx.prod) {
    if (
      cfg.build.ignorePublicFolder !== true &&
      configName !== webpackNames.ssr.serverSide
    ) {
      // copy /public to dist folder
      const CopyWebpackPlugin = require('copy-webpack-plugin')

      const ignore = [
        '**/.DS_Store',
        '**/.Thumbs.db',
        '**/*.sublime*',
        '**/.idea',
        '**/.editorconfig',
        '**/.vscode'
      ]

      // avoid useless files to be copied
      if (['electron', 'cordova', 'capacitor'].includes(cfg.ctx.modeName)) {
        ignore.push(
          '**/public/icons', '**/public/favicon.ico'
        )
      }

      const patterns = [{
        from: appPaths.resolve.app('public'),
        noErrorOnMissing: true,
        globOptions: { ignore }
      }]

      chain.plugin('copy-webpack')
        .use(CopyWebpackPlugin, [{ patterns }])
    }

    chain.optimization
      .concatenateModules(true)

    if (cfg.ctx.debug) {
      // reset default webpack 4 minimizer
      chain.optimization.minimizers.delete('js')
      // also:
      chain.optimization.minimize(false)
    }
    else if (cfg.build.minify) {
      const TerserPlugin = require('terser-webpack-plugin')

      chain.optimization
        .minimizer('js')
        .use(TerserPlugin, [{
          terserOptions: cfg.build.uglifyOptions,
          extractComments: false,
          parallel: true
        }])
    }

    if (configName !== webpackNames.ssr.serverSide) {
      // dedupe & minify CSS (only if extracted)
      if (cfg.build.extractCSS && cfg.build.minify) {
        const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

        // We are using this plugin so that possible
        // duplicated CSS = require(different components) can be deduped.
        chain.optimization
          .minimizer('css')
          .use(CssMinimizerPlugin, [{
            parallel: true
          }])
      }

      // also produce a gzipped version
      if (cfg.build.gzip) {
        const CompressionWebpackPlugin = require('compression-webpack-plugin')
        chain.plugin('compress-webpack')
          .use(CompressionWebpackPlugin, [ cfg.build.gzip ])
      }

      if (cfg.build.analyze) {
        const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
        chain.plugin('bundle-analyzer')
          .use(BundleAnalyzerPlugin, [ Object.assign({}, cfg.build.analyze) ])
      }
    }
  }

  return chain
}
<commit_msg>fix(app): revert to esModule:false for media assets<commit_after>const path = require('path')
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const WebpackChain = require('webpack-chain')
const { VueLoaderPlugin } = require('vue-loader')

const WebpackProgressPlugin = require('./plugin.progress')
const BootDefaultExport = require('./plugin.boot-default-export')
const parseBuildEnv = require('../helpers/parse-build-env')

const appPaths = require('../app-paths')
const injectStyleRules = require('./inject.style-rules')
const { webpackNames } = require('./symbols')

function getDependenciesRegex (list) {
  const deps = list.map(dep => {
    if (typeof dep === 'string') {
      return path.join('node_modules', dep, '/')
        .replace(/\\/g, '[\\\\/]') // windows support
    }
    else if (dep instanceof RegExp) {
      return dep.source
    }
  })

  return new RegExp(deps.join('|'))
}

function getRootDefines (rootDefines, configName) {
  if (configName === webpackNames.ssr.serverSide) {
    return { ...rootDefines, __QUASAR_SSR_SERVER__: true }
  }

  if (configName === webpackNames.ssr.clientSide) {
    return { ...rootDefines, __QUASAR_SSR_CLIENT__: true }
  }

  return rootDefines
}

module.exports = function (cfg, configName) {
  const chain = new WebpackChain()

  const needsHash = !cfg.ctx.dev && !['electron', 'cordova', 'capacitor', 'bex'].includes(cfg.ctx.modeName)
  const fileHash = needsHash ? '.[contenthash:8]' : ''
  const chunkHash = needsHash ? '.[chunkhash:8]' : ''
  const resolveModules = [
    'node_modules',
    appPaths.resolve.app('node_modules'),
    appPaths.resolve.cli('node_modules')
  ]

  chain.entry('app').add(appPaths.resolve.app('.quasar/client-entry.js'))
  chain.mode(cfg.ctx.dev ? 'development' : 'production')
  chain.devtool(cfg.build.sourceMap ? cfg.build.devtool : false)

  if (cfg.ctx.prod || cfg.ctx.mode.ssr) {
    chain.output
      .path(
        cfg.ctx.mode.ssr
          ? path.join(cfg.build.distDir, 'www')
          : cfg.build.distDir
      )
      .publicPath(cfg.build.publicPath)
      .filename(`js/[name]${fileHash}.js`)
      .chunkFilename(`js/[name]${chunkHash}.js`)
  }

  chain.resolve.symlinks(false)

  chain.resolve.extensions
    .merge(
      cfg.supportTS !== false
        ? [ '.mjs', '.ts', '.js', '.vue', '.json', '.wasm' ]
        : [ '.mjs', '.js', '.vue', '.json', '.wasm' ]
    )

  chain.resolve.modules
    .merge(resolveModules)

  chain.resolve.alias
    .merge({
      src: appPaths.srcDir,
      app: appPaths.appDir,
      components: appPaths.resolve.src(`components`),
      layouts: appPaths.resolve.src(`layouts`),
      pages: appPaths.resolve.src(`pages`),
      assets: appPaths.resolve.src(`assets`),
      boot: appPaths.resolve.src(`boot`),

      'src-bex': appPaths.bexDir // needed for app/templates
    })

  const vueFile = configName === webpackNames.ssr.serverSide
    ? (cfg.ctx.prod ? 'vue.cjs.prod.js' : 'vue.cjs.js')
    : (
      cfg.build.vueCompiler
        ? 'vue.esm-bundler.js'
        : 'vue.runtime.esm-bundler.js'
    )

  chain.resolve.alias.set('vue$', 'vue/dist/' + vueFile)

  const vueI18nFile = configName === webpackNames.ssr.serverSide
    ? (cfg.ctx.prod ? 'vue-i18n.cjs.prod.js' : 'vue-i18n.cjs.js')
    : 'vue-i18n.esm-bundler.js'

  chain.resolve.alias.set('vue-i18n$', 'vue-i18n/dist/' + vueI18nFile)

  chain.resolveLoader.modules
    .merge(resolveModules)

  chain.module.noParse(
    /^(vue|vue-router|vuex|vuex-router-sync|@quasar[\\/]extras|quasar[\\/]dist)$/
  )

  const vueRule = chain.module.rule('vue')
    .test(/\.vue$/)

  vueRule.use('vue-auto-import-quasar')
    .loader(path.join(__dirname, 'loader.vue.auto-import-quasar.js'))
    .options({
      autoImportComponentCase: cfg.framework.autoImportComponentCase,
      isServerBuild: configName === webpackNames.ssr.serverSide
    })

  vueRule.use('vue-loader')
    .loader('vue-loader')
    .options(
      merge(
        cfg.build.vueLoaderOptions,
        {
          isServerBuild: configName === webpackNames.ssr.serverSide,
          compilerOptions: configName === webpackNames.ssr.serverSide
            ? { directiveTransforms: cfg.ssr.directiveTransforms, ssr: true }
            : {}
        }
      )
    )

  if (configName !== webpackNames.ssr.serverSide) {
    chain.module.rule('js-transform-quasar-imports')
      .test(/\.(t|j)sx?$/)
      .use('transform-quasar-imports')
        .loader(path.join(__dirname, 'loader.js.transform-quasar-imports.js'))
  }

  if (cfg.build.transpile === true) {
    const nodeModulesRegex = /[\\/]node_modules[\\/]/
    const exceptionsRegex = getDependenciesRegex(
      [ /\.vue\.js$/, configName === webpackNames.ssr.serverSide ? 'quasar/src' : 'quasar', '@babel/runtime' ]
        .concat(cfg.build.transpileDependencies)
    )

    chain.module.rule('babel')
      .test(/\.js$/)
      .exclude
        .add(filepath => (
          // Transpile the exceptions:
          exceptionsRegex.test(filepath) === false &&
          // Don't transpile anything else in node_modules:
          nodeModulesRegex.test(filepath)
        ))
        .end()
      .use('babel-loader')
        .loader('babel-loader')
          .options({
            compact: false,
            extends: appPaths.resolve.app('babel.config.js')
          })
  }

  if (cfg.supportTS !== false) {
    chain.module
      .rule('typescript')
      .test(/\.ts$/)
      .use('ts-loader')
        .loader('ts-loader')
        .options({
          // custom config is merged if present, but vue setup and type checking disable are always applied
          ...(cfg.supportTS.tsLoaderConfig || {}),
          appendTsSuffixTo: [ /\.vue$/ ],
          // Type checking is handled by fork-ts-checker-webpack-plugin
          transpileOnly: true
        })

    const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
    chain
      .plugin('ts-checker')
      // https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options
      .use(ForkTsCheckerWebpackPlugin, [
        // custom config is merged if present, but vue option is always enabled
        merge({}, cfg.supportTS.tsCheckerConfig || {}, {
          typescript: {
            extensions: {
              vue: {
                enabled: true,
                compiler: '@vue/compiler-sfc'
              }
            }
          }
        })
      ])
  }

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('images')
    .test(/\.(png|jpe?g|gif|svg|webp|avif|ico)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        esModule: false,
        limit: 10000,
        name: `img/[name]${fileHash}.[ext]`
      })

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('fonts')
    .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        esModule: false,
        limit: 10000,
        name: `fonts/[name]${fileHash}.[ext]`
      })

  // TODO: change to Asset Management when webpack-chain is webpack5 compatible
  chain.module.rule('media')
    .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
    .type('javascript/auto')
    .use('url-loader')
      .loader('url-loader')
      .options({
        esModule: false,
        limit: 10000,
        name: `media/[name]${fileHash}.[ext]`
      })

  injectStyleRules(chain, {
    isServerBuild: configName === webpackNames.ssr.serverSide,
    rtl: cfg.build.rtl,
    sourceMap: cfg.build.sourceMap,
    extract: cfg.build.extractCSS,
    minify: cfg.build.minify,
    stylusLoaderOptions: cfg.build.stylusLoaderOptions,
    sassLoaderOptions: cfg.build.sassLoaderOptions,
    scssLoaderOptions: cfg.build.scssLoaderOptions,
    lessLoaderOptions: cfg.build.lessLoaderOptions
  })

  chain.module // fixes https://github.com/graphql/graphql-js/issues/1272
    .rule('mjs')
    .test(/\.mjs$/)
    .type('javascript/auto')
    .include
      .add(/[\\/]node_modules[\\/]/)

  chain.plugin('vue-loader')
    .use(VueLoaderPlugin)

  chain.plugin('define')
    .use(webpack.DefinePlugin, [
      parseBuildEnv(cfg.build.env, getRootDefines(cfg.__rootDefines, configName))
    ])

  if (cfg.ctx.dev && configName !== webpackNames.ssr.serverSide && cfg.ctx.mode.pwa && cfg.pwa.workboxPluginMode === 'InjectManifest') {
    // need to place it here before the status plugin
    const CustomSwWarningPlugin = require('./pwa/plugin.custom-sw-warning')
    chain.plugin('custom-sw-warning')
      .use(CustomSwWarningPlugin)
  }

  chain.plugin('progress')
    .use(WebpackProgressPlugin, [{ name: configName, cfg }])

  chain.plugin('boot-default-export')
    .use(BootDefaultExport)

  chain.performance
    .hints(false)
    .maxAssetSize(500000)

  if (configName !== webpackNames.ssr.serverSide && cfg.vendor.disable !== true) {
    const { add, remove } = cfg.vendor
    const regex = /[\\/]node_modules[\\/]/

    chain.optimization.splitChunks({
      cacheGroups: {
        defaultVendors: {
          name: 'vendor',
          chunks: 'all',
          priority: -10,
          // a module is extracted into the vendor chunk if...
          test: add !== void 0 || remove !== void 0
            ? module => {
              if (module.resource) {
                if (remove !== void 0 && remove.test(module.resource)) { return false }
                if (add !== void 0 && add.test(module.resource)) { return true }
              }
              return regex.test(module.resource)
            }
            : regex
        },
        common: {
          name: `chunk-common`,
          minChunks: 2,
          priority: -20,
          chunks: 'all',
          reuseExistingChunk: true
        }
      }
    })
  }

  // extract css into its own file
  if (configName !== webpackNames.ssr.serverSide && cfg.build.extractCSS) {
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')

    chain.plugin('mini-css-extract')
      .use(MiniCssExtractPlugin, [{
        filename: `css/[name]${fileHash}.css`
      }])
  }

  if (cfg.ctx.prod) {
    if (
      cfg.build.ignorePublicFolder !== true &&
      configName !== webpackNames.ssr.serverSide
    ) {
      // copy /public to dist folder
      const CopyWebpackPlugin = require('copy-webpack-plugin')

      const ignore = [
        '**/.DS_Store',
        '**/.Thumbs.db',
        '**/*.sublime*',
        '**/.idea',
        '**/.editorconfig',
        '**/.vscode'
      ]

      // avoid useless files to be copied
      if (['electron', 'cordova', 'capacitor'].includes(cfg.ctx.modeName)) {
        ignore.push(
          '**/public/icons', '**/public/favicon.ico'
        )
      }

      const patterns = [{
        from: appPaths.resolve.app('public'),
        noErrorOnMissing: true,
        globOptions: { ignore }
      }]

      chain.plugin('copy-webpack')
        .use(CopyWebpackPlugin, [{ patterns }])
    }

    chain.optimization
      .concatenateModules(true)

    if (cfg.ctx.debug) {
      // reset default webpack 4 minimizer
      chain.optimization.minimizers.delete('js')
      // also:
      chain.optimization.minimize(false)
    }
    else if (cfg.build.minify) {
      const TerserPlugin = require('terser-webpack-plugin')

      chain.optimization
        .minimizer('js')
        .use(TerserPlugin, [{
          terserOptions: cfg.build.uglifyOptions,
          extractComments: false,
          parallel: true
        }])
    }

    if (configName !== webpackNames.ssr.serverSide) {
      // dedupe & minify CSS (only if extracted)
      if (cfg.build.extractCSS && cfg.build.minify) {
        const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

        // We are using this plugin so that possible
        // duplicated CSS = require(different components) can be deduped.
        chain.optimization
          .minimizer('css')
          .use(CssMinimizerPlugin, [{
            parallel: true
          }])
      }

      // also produce a gzipped version
      if (cfg.build.gzip) {
        const CompressionWebpackPlugin = require('compression-webpack-plugin')
        chain.plugin('compress-webpack')
          .use(CompressionWebpackPlugin, [ cfg.build.gzip ])
      }

      if (cfg.build.analyze) {
        const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
        chain.plugin('bundle-analyzer')
          .use(BundleAnalyzerPlugin, [ Object.assign({}, cfg.build.analyze) ])
      }
    }
  }

  return chain
}
<|endoftext|>