nats-hemera
Advanced tools
Comparing version 0.3.16 to 0.3.17
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ 'use strict'; |
@@ -0,0 +0,0 @@ 'use strict'; |
@@ -0,0 +0,0 @@ 'use strict'; |
@@ -29,2 +29,6 @@ 'use strict'; | ||
var _pino = require('pino'); | ||
var _pino2 = _interopRequireDefault(_pino); | ||
var _errors = require('./errors'); | ||
@@ -58,6 +62,2 @@ | ||
var _logger = require('./logger'); | ||
var _logger2 = _interopRequireDefault(_logger); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -81,6 +81,6 @@ | ||
// config | ||
var defaultConfig = { | ||
timeout: 2000, | ||
debug: false, | ||
name: 'app', | ||
crashOnFatal: true, | ||
@@ -100,2 +100,10 @@ logLevel: 'silent', | ||
/** | ||
* Creates an instance of Hemera | ||
* | ||
* @param {Nats} transport | ||
* @param {Config} params | ||
* | ||
* @memberOf Hemera | ||
*/ | ||
function Hemera(transport, params) { | ||
@@ -113,3 +121,3 @@ _classCallCheck(this, Hemera); | ||
// special variables for new execution context | ||
// special variables for the new execution context | ||
_this.context$ = {}; | ||
@@ -135,2 +143,4 @@ _this.meta$ = {}; | ||
// contains the list of all registered plugins | ||
// the core is a plugin to | ||
_this._plugins = { | ||
@@ -156,32 +166,35 @@ core: _this.plugin$.attributes | ||
// start tracking process stats | ||
_this._heavy.start(); | ||
/** | ||
* Will be executed before the client request is executed. | ||
*/ | ||
// will be executed before the client request is executed. | ||
_this._extensions.onClientPreRequest.addRange(_extensions2.default.onClientPreRequest); | ||
/** | ||
* Will be executed after the client received and decoded the request. | ||
*/ | ||
// will be executed after the client received and decoded the request | ||
_this._extensions.onClientPostRequest.addRange(_extensions2.default.onClientPostRequest); | ||
/** | ||
* Will be executed before the server received the request. | ||
*/ | ||
// will be executed before the server received the requests | ||
_this._extensions.onServerPreRequest.addRange(_extensions2.default.onServerPreRequest); | ||
/** | ||
* Will be executed before the server action is executed. | ||
*/ | ||
// will be executed before the server action is executed | ||
_this._extensions.onServerPreHandler.addRange(_extensions2.default.onServerPreHandler); | ||
/** | ||
* Will be executed before the server reply the response and build the message. | ||
*/ | ||
// will be executed before the server reply the response and build the message | ||
_this._extensions.onServerPreResponse.addRange(_extensions2.default.onServerPreResponse); | ||
_this.log = _this._config.logger || new _logger2.default({ | ||
level: _this._config.logLevel | ||
}); | ||
// use own logger | ||
if (_this._config.logger) { | ||
_this.log = _this._config.logger; | ||
} else { | ||
var Pretty = _pino2.default.pretty(); | ||
//Leads to too much listeners in tests | ||
if (_this._config.logLevel !== 'silent') { | ||
Pretty.pipe(process.stdout); | ||
} | ||
_this.log = (0, _pino2.default)({ | ||
name: _this._config.name, | ||
safe: true, | ||
level: _this._config.logLevel | ||
}, _pino2.default.pretty()); | ||
} | ||
return _this; | ||
@@ -191,2 +204,4 @@ } | ||
/** | ||
* Return all registered plugins | ||
* | ||
* @readonly | ||
@@ -203,4 +218,5 @@ * | ||
/** | ||
* Exposed data in context of the current plugin | ||
* Is accessible by this.expositions[<plugin>][<key>] | ||
* | ||
* | ||
* @param {string} key | ||
@@ -226,2 +242,4 @@ * @param {mixed} object | ||
/** | ||
* Return the underlying NATS driver | ||
* | ||
* @readonly | ||
@@ -235,5 +253,7 @@ * | ||
/** | ||
* Add an extension. Extensions are called in serie and can only pass an error | ||
* You can work with the current context manipulate something | ||
* | ||
* | ||
* @param {any} type | ||
@@ -256,3 +276,6 @@ * @param {any} handler | ||
} | ||
/** | ||
* Use a plugin. | ||
* | ||
* @param {any} plugin | ||
@@ -290,4 +313,5 @@ * | ||
/** | ||
* Change the current plugin configuration | ||
* e.g to set the payload validator | ||
* | ||
* | ||
* @param {any} options | ||
@@ -306,5 +330,5 @@ * | ||
/** | ||
* Change the base configuration. | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -321,2 +345,4 @@ */ | ||
/** | ||
* Exit the process | ||
* | ||
* @memberOf Hemera | ||
@@ -335,4 +361,6 @@ */ | ||
/** | ||
* @param {any} cb | ||
* | ||
* | ||
* @param {Function} cb | ||
* | ||
* @memberOf Hemera | ||
@@ -370,3 +398,3 @@ */ | ||
/** | ||
* Add response | ||
* Publishing with the NATS driver | ||
* | ||
@@ -386,3 +414,3 @@ * @returns | ||
/** | ||
* Act | ||
* Send request with the NATS driver | ||
* | ||
@@ -402,5 +430,5 @@ * @returns | ||
/** | ||
* Build the final payload for the response | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -436,8 +464,10 @@ */ | ||
// final response | ||
this._message = m.value; | ||
} | ||
/** | ||
* Last step before the response is send to the callee. | ||
* The preResponse extension is invoked and previous errors are evaluated. | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -458,3 +488,2 @@ */ | ||
self.log.error(self._response); | ||
self._buildMessage(); | ||
} | ||
@@ -467,11 +496,11 @@ // check for an extension error | ||
self.log.error(self._response); | ||
self._buildMessage(); | ||
} else { | ||
self._buildMessage(); | ||
} | ||
// create message payload | ||
self._buildMessage(); | ||
// indicates that an error occurs and that the program should exit | ||
if (self._shouldCrash) { | ||
// only when we have an inbox othwerwise exit the service immediately | ||
if (self._replyTo) { | ||
@@ -494,2 +523,3 @@ | ||
// reply only when we have an inbox | ||
if (self._replyTo) { | ||
@@ -503,5 +533,9 @@ | ||
/** | ||
* @param {any} topic | ||
* @returns | ||
* Attach one handler to the topic subscriber. | ||
* With subToMany and maxMessages you control NATS specific behaviour. | ||
* | ||
* @param {string} topic | ||
* @param {boolean} subToMany | ||
* @param {number} maxMessages | ||
* | ||
* @memberOf Hemera | ||
@@ -530,6 +564,6 @@ */ | ||
ctx._request = request; | ||
ctx._response = {}; | ||
ctx._pattern = {}; | ||
ctx._actMeta = {}; | ||
//Extension point 'onServerPreRequest' | ||
self._extensions.onServerPreRequest.invoke(ctx, function (err) { | ||
@@ -542,3 +576,2 @@ | ||
var error = new _errors2.default.HemeraError(_constants2.default.EXTENSION_ERROR).causedBy(err); | ||
self.log.error(error); | ||
@@ -550,2 +583,3 @@ self._response = error; | ||
// find matched RPC | ||
var requestType = self._request.value.request.type; | ||
@@ -573,3 +607,3 @@ self._pattern = self._request.value.pattern; | ||
// if request type is 'pubsub' we dont have to answer | ||
// if request type is 'pubsub' we dont have to reply back | ||
if (requestType === 'pubsub') { | ||
@@ -582,3 +616,3 @@ | ||
// call action | ||
// execute RPC action | ||
action(self._request.value.pattern, function (err, resp) { | ||
@@ -595,2 +629,3 @@ | ||
// assign action result | ||
self._response = resp; | ||
@@ -606,2 +641,3 @@ | ||
// service should exit | ||
self._shouldCrash = true; | ||
@@ -647,2 +683,4 @@ | ||
/** | ||
* The topic is subscribed on NATS and can be called from any client. | ||
* | ||
* @param {any} pattern | ||
@@ -685,3 +723,3 @@ * @param {any} cb | ||
// remove objects (rules) from pattern and extract scheme | ||
// remove objects (rules) from pattern and extract schema | ||
_lodash2.default.each(pattern, function (v, k) { | ||
@@ -729,2 +767,4 @@ | ||
/** | ||
* Start an action. | ||
* | ||
* @param {any} pattern | ||
@@ -883,2 +923,7 @@ * @param {any} cb | ||
/** | ||
* Handle the timeout when a pattern could not be resolved. Can have different reasons: | ||
* - No one was connected at the time (service unavailable) | ||
* - Service is actually still processing the request (service takes too long) | ||
* - Service was processing the request but crashed (service error) | ||
* | ||
* @param {any} sid | ||
@@ -931,5 +976,7 @@ * @param {any} pattern | ||
/** | ||
* Create new instance of hemera but with pointer on the previous propertys | ||
* so we are able to create a scope per act without lossing the reference to the core api. | ||
* | ||
* @returns | ||
* OLOO (objects-linked-to-other-objects) is a code style which creates and relates objects directly without the abstraction of classes. OLOO quite naturally * implements [[Prototype]]-based behavior delegation. | ||
* More details: {@link https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch6.md} | ||
* | ||
* @memberOf Hemera | ||
@@ -944,4 +991,2 @@ */ | ||
// create new instance of hemera but with pointer on the previous propertys | ||
// so we are able to create a scope per act without lossing the reference to the core api. | ||
var ctx = Object.create(self); | ||
@@ -953,2 +998,4 @@ | ||
/** | ||
* Return the list of all registered actions | ||
* | ||
* @memberOf Hemera | ||
@@ -965,2 +1012,4 @@ */ | ||
/** | ||
* Close the process watcher and the underlying transort driver. | ||
* | ||
* @returns | ||
@@ -987,2 +1036,4 @@ * | ||
/** | ||
* Return the bloomrun instance | ||
* | ||
* @readonly | ||
@@ -1001,4 +1052,4 @@ * | ||
/** | ||
* Return the heavy instance | ||
* | ||
* | ||
* @readonly | ||
@@ -1017,4 +1068,4 @@ * | ||
/** | ||
* Return the shared object of all exposed data | ||
* | ||
* | ||
* @readonly | ||
@@ -1039,2 +1090,4 @@ * @type {Exposition} | ||
/** | ||
* Return all registered topics | ||
* | ||
* @readonly | ||
@@ -1041,0 +1094,0 @@ * |
'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
/*! | ||
* hemera | ||
* Copyright(c) 2016 Dustin Deus (deusdustin@gmail.com) | ||
* MIT Licensed | ||
*/ | ||
var _hoek = require('hoek'); | ||
@@ -23,2 +15,8 @@ | ||
/*! | ||
* hemera | ||
* Copyright(c) 2016 Dustin Deus (deusdustin@gmail.com) | ||
* MIT Licensed | ||
*/ | ||
var Pretty = _pino2.default.pretty(); | ||
@@ -36,60 +34,32 @@ | ||
var Logger = function () { | ||
/** | ||
* Creates an instance of Logger. | ||
* | ||
* @param {any} params | ||
* | ||
* @memberOf Logger | ||
*/ | ||
function Logger(params) { | ||
var _this = this; | ||
var Logger = | ||
/** | ||
* Creates an instance of Logger. | ||
* | ||
* @param {any} params | ||
* | ||
* @memberOf Logger | ||
*/ | ||
function Logger(params) { | ||
_classCallCheck(this, Logger); | ||
_classCallCheck(this, Logger); | ||
var self = this; | ||
var self = this; | ||
self._config = _hoek2.default.applyToDefaults(defaultConfig, params || {}); | ||
self._config = _hoek2.default.applyToDefaults(defaultConfig, params || {}); | ||
//Leads to too much listeners in tests | ||
if (this._config.level !== 'silent') { | ||
Pretty.pipe(process.stdout); | ||
} | ||
this._logger = (0, _pino2.default)({ | ||
name: 'app', | ||
safe: true, | ||
level: this._config.level | ||
}, Pretty); | ||
//Set levels, create new prototype methods | ||
self._config.levels.forEach(function (level) { | ||
var that = _this; | ||
that[level] = function () { | ||
var args = [level].concat(Array.prototype.slice.call(arguments)); | ||
self.log.apply(self, args); | ||
}; | ||
}); | ||
//Leads to too much listeners in tests | ||
if (this._config.level !== 'silent') { | ||
Pretty.pipe(process.stdout); | ||
} | ||
/** | ||
* @memberOf Logger | ||
*/ | ||
this._logger = (0, _pino2.default)({ | ||
name: 'app', | ||
safe: true, | ||
level: this._config.level | ||
}, Pretty); | ||
this.__proto__ = this._logger; | ||
}; | ||
_createClass(Logger, [{ | ||
key: 'log', | ||
value: function log() { | ||
this._logger[arguments[0]].apply(this._logger, Array.prototype.slice.call(arguments).slice(1)); | ||
} | ||
}]); | ||
return Logger; | ||
}(); | ||
module.exports = Logger; | ||
//# sourceMappingURL=logger.js.map |
@@ -0,0 +0,0 @@ /*! |
@@ -0,0 +0,0 @@ // @flow |
@@ -0,0 +0,0 @@ // @flow |
@@ -0,0 +0,0 @@ // @flow |
160
lib/index.js
@@ -19,2 +19,3 @@ // @flow | ||
import _ from 'lodash' | ||
import Pino from 'pino' | ||
@@ -28,8 +29,7 @@ import Errors from './errors' | ||
import DefaultDecoder from './decoder' | ||
import DefaultLogger from './logger' | ||
// config | ||
var defaultConfig: Config = { | ||
timeout: 2000, | ||
debug: false, | ||
name: 'app', | ||
crashOnFatal: true, | ||
@@ -84,2 +84,11 @@ logLevel: 'silent', | ||
/** | ||
* Creates an instance of Hemera | ||
* | ||
* @param {Nats} transport | ||
* @param {Config} params | ||
* | ||
* @memberOf Hemera | ||
*/ | ||
constructor(transport: Nats, params: Config) { | ||
@@ -96,3 +105,3 @@ | ||
// special variables for new execution context | ||
// special variables for the new execution context | ||
this.context$ = {} | ||
@@ -118,2 +127,4 @@ this.meta$ = {} | ||
// contains the list of all registered plugins | ||
// the core is a plugin to | ||
this._plugins = { | ||
@@ -139,35 +150,40 @@ core: this.plugin$.attributes | ||
// start tracking process stats | ||
this._heavy.start() | ||
/** | ||
* Will be executed before the client request is executed. | ||
*/ | ||
// will be executed before the client request is executed. | ||
this._extensions.onClientPreRequest.addRange(DefaultExtensions.onClientPreRequest) | ||
/** | ||
* Will be executed after the client received and decoded the request. | ||
*/ | ||
// will be executed after the client received and decoded the request | ||
this._extensions.onClientPostRequest.addRange(DefaultExtensions.onClientPostRequest) | ||
/** | ||
* Will be executed before the server received the request. | ||
*/ | ||
// will be executed before the server received the requests | ||
this._extensions.onServerPreRequest.addRange(DefaultExtensions.onServerPreRequest) | ||
/** | ||
* Will be executed before the server action is executed. | ||
*/ | ||
// will be executed before the server action is executed | ||
this._extensions.onServerPreHandler.addRange(DefaultExtensions.onServerPreHandler) | ||
/** | ||
* Will be executed before the server reply the response and build the message. | ||
*/ | ||
// will be executed before the server reply the response and build the message | ||
this._extensions.onServerPreResponse.addRange(DefaultExtensions.onServerPreResponse) | ||
this.log = this._config.logger || new DefaultLogger({ | ||
level: this._config.logLevel | ||
}) | ||
// use own logger | ||
if (this._config.logger) { | ||
this.log = this._config.logger | ||
} else { | ||
let Pretty = Pino.pretty() | ||
//Leads to too much listeners in tests | ||
if (this._config.logLevel !== 'silent') { | ||
Pretty.pipe(process.stdout) | ||
} | ||
this.log = Pino({ | ||
name: this._config.name, | ||
safe: true, | ||
level: this._config.logLevel | ||
}, Pino.pretty()) | ||
} | ||
} | ||
/** | ||
* Return all registered plugins | ||
* | ||
* @readonly | ||
@@ -185,2 +201,4 @@ * | ||
/** | ||
* Return the bloomrun instance | ||
* | ||
* @readonly | ||
@@ -196,4 +214,4 @@ * | ||
/** | ||
* Return the heavy instance | ||
* | ||
* | ||
* @readonly | ||
@@ -209,4 +227,4 @@ * | ||
/** | ||
* Return the shared object of all exposed data | ||
* | ||
* | ||
* @readonly | ||
@@ -222,4 +240,5 @@ * @type {Exposition} | ||
/** | ||
* Exposed data in context of the current plugin | ||
* Is accessible by this.expositions[<plugin>][<key>] | ||
* | ||
* | ||
* @param {string} key | ||
@@ -246,2 +265,4 @@ * @param {mixed} object | ||
/** | ||
* Return the underlying NATS driver | ||
* | ||
* @readonly | ||
@@ -257,2 +278,4 @@ * | ||
/** | ||
* Return all registered topics | ||
* | ||
* @readonly | ||
@@ -267,5 +290,7 @@ * | ||
} | ||
/** | ||
* Add an extension. Extensions are called in serie and can only pass an error | ||
* You can work with the current context manipulate something | ||
* | ||
* | ||
* @param {any} type | ||
@@ -289,3 +314,6 @@ * @param {any} handler | ||
} | ||
/** | ||
* Use a plugin. | ||
* | ||
* @param {any} plugin | ||
@@ -321,4 +349,5 @@ * | ||
/** | ||
* Change the current plugin configuration | ||
* e.g to set the payload validator | ||
* | ||
* | ||
* @param {any} options | ||
@@ -334,5 +363,5 @@ * | ||
/** | ||
* Change the base configuration. | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -346,2 +375,4 @@ */ | ||
/** | ||
* Exit the process | ||
* | ||
* @memberOf Hemera | ||
@@ -357,4 +388,6 @@ */ | ||
/** | ||
* @param {any} cb | ||
* | ||
* | ||
* @param {Function} cb | ||
* | ||
* @memberOf Hemera | ||
@@ -386,3 +419,3 @@ */ | ||
/** | ||
* Add response | ||
* Publishing with the NATS driver | ||
* | ||
@@ -399,3 +432,3 @@ * @returns | ||
/** | ||
* Act | ||
* Send request with the NATS driver | ||
* | ||
@@ -412,5 +445,5 @@ * @returns | ||
/** | ||
* Build the final payload for the response | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -443,9 +476,11 @@ */ | ||
// final response | ||
this._message = m.value | ||
} | ||
/** | ||
* Last step before the response is send to the callee. | ||
* The preResponse extension is invoked and previous errors are evaluated. | ||
* | ||
* | ||
* | ||
* @memberOf Hemera | ||
@@ -463,3 +498,2 @@ */ | ||
self.log.error(self._response) | ||
self._buildMessage() | ||
} | ||
@@ -472,11 +506,11 @@ // check for an extension error | ||
self.log.error(self._response) | ||
self._buildMessage() | ||
} else { | ||
self._buildMessage() | ||
} | ||
// create message payload | ||
self._buildMessage() | ||
// indicates that an error occurs and that the program should exit | ||
if (self._shouldCrash) { | ||
// only when we have an inbox othwerwise exit the service immediately | ||
if (self._replyTo) { | ||
@@ -501,2 +535,3 @@ | ||
// reply only when we have an inbox | ||
if (self._replyTo) { | ||
@@ -512,5 +547,9 @@ | ||
/** | ||
* @param {any} topic | ||
* @returns | ||
* Attach one handler to the topic subscriber. | ||
* With subToMany and maxMessages you control NATS specific behaviour. | ||
* | ||
* @param {string} topic | ||
* @param {boolean} subToMany | ||
* @param {number} maxMessages | ||
* | ||
* @memberOf Hemera | ||
@@ -535,6 +574,6 @@ */ | ||
ctx._request = request | ||
ctx._response = {} | ||
ctx._pattern = {} | ||
ctx._actMeta = {} | ||
//Extension point 'onServerPreRequest' | ||
self._extensions.onServerPreRequest.invoke(ctx, function (err) { | ||
@@ -547,3 +586,2 @@ | ||
let error = new Errors.HemeraError(Constants.EXTENSION_ERROR).causedBy(err) | ||
self.log.error(error) | ||
@@ -555,2 +593,3 @@ self._response = error | ||
// find matched RPC | ||
let requestType = self._request.value.request.type | ||
@@ -578,3 +617,3 @@ self._pattern = self._request.value.pattern | ||
// if request type is 'pubsub' we dont have to answer | ||
// if request type is 'pubsub' we dont have to reply back | ||
if (requestType === 'pubsub') { | ||
@@ -587,3 +626,3 @@ | ||
// call action | ||
// execute RPC action | ||
action(self._request.value.pattern, (err: Error, resp) => { | ||
@@ -600,2 +639,3 @@ | ||
// assign action result | ||
self._response = resp | ||
@@ -612,2 +652,3 @@ | ||
// service should exit | ||
self._shouldCrash = true | ||
@@ -658,2 +699,4 @@ | ||
/** | ||
* The topic is subscribed on NATS and can be called from any client. | ||
* | ||
* @param {any} pattern | ||
@@ -695,3 +738,3 @@ * @param {any} cb | ||
// remove objects (rules) from pattern and extract scheme | ||
// remove objects (rules) from pattern and extract schema | ||
_.each(pattern, function (v: string, k: any) { | ||
@@ -739,2 +782,4 @@ | ||
/** | ||
* Start an action. | ||
* | ||
* @param {any} pattern | ||
@@ -896,2 +941,7 @@ * @param {any} cb | ||
/** | ||
* Handle the timeout when a pattern could not be resolved. Can have different reasons: | ||
* - No one was connected at the time (service unavailable) | ||
* - Service is actually still processing the request (service takes too long) | ||
* - Service was processing the request but crashed (service error) | ||
* | ||
* @param {any} sid | ||
@@ -942,5 +992,7 @@ * @param {any} pattern | ||
/** | ||
* Create new instance of hemera but with pointer on the previous propertys | ||
* so we are able to create a scope per act without lossing the reference to the core api. | ||
* | ||
* @returns | ||
* OLOO (objects-linked-to-other-objects) is a code style which creates and relates objects directly without the abstraction of classes. OLOO quite naturally * implements [[Prototype]]-based behavior delegation. | ||
* More details: {@link https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch6.md} | ||
* | ||
* @memberOf Hemera | ||
@@ -952,4 +1004,2 @@ */ | ||
// create new instance of hemera but with pointer on the previous propertys | ||
// so we are able to create a scope per act without lossing the reference to the core api. | ||
var ctx: Hemera = Object.create(self) | ||
@@ -961,2 +1011,4 @@ | ||
/** | ||
* Return the list of all registered actions | ||
* | ||
* @memberOf Hemera | ||
@@ -970,2 +1022,4 @@ */ | ||
/** | ||
* Close the process watcher and the underlying transort driver. | ||
* | ||
* @returns | ||
@@ -972,0 +1026,0 @@ * |
{ | ||
"name": "nats-hemera", | ||
"author": "Dustin Deus (https://github.com/StarpTech)", | ||
"version": "0.3.16", | ||
"version": "0.3.17", | ||
"main": "build/index.js", | ||
@@ -6,0 +6,0 @@ "homepage": "https://hemerajs.github.io/hemera/", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
143177
2492
37