UNPKG

agentstack

Version:

Enterprise Application Stack for TypeScript

16 lines (13 loc) 39.8 kB
/* Application Stack for Enterprise Applications */'use strict';Object.defineProperty(exports,'__esModule',{value:!0});var util=require('util'),agentframework=require('agentframework'),path=require('path'),fs=require('fs'),url=require('url'),events=require('events'),yaml=require('js-yaml'),safeStringify=require('json-stringify-safe'),http=require('http'),os=require('os'),retrier=require('retry');class Exception extends Error{constructor(){const e=Exception.parseArguments(arguments);agentframework.IsNullOrUndefined(e.msg)?super():super(e.msg),this.cause=e.err,this.code=e.code,this.context=e.obj;const t=this.constructor.prototype.constructor.name;this.name=agentframework.IsNullOrUndefined(this.code)?this.constructor.prototype.constructor.name:'['+this.code+'] '+this.constructor.prototype.constructor.name;const n=this.message;agentframework.IsNullOrUndefined(this.context)||(this.message+=' ('+util.inspect(this.context)+')'),Error.captureStackTrace(this,new.target),this.name=t,this.message=n,Exception.buildNestedErrorStackTrace(this,this.cause)}static parseArguments(e){let t,n,i,s,r,o=e.length-1;for(t=0;t<=o;t++)if(!n&&e[t]instanceof Error)n=e[t];else if(!i&&'number'==typeof e[t])i=e[t];else if(!s&&'object'==typeof e[t])s=e[t];else{r=e[t];break}if(o>t){let n=Array.prototype.slice.call(e,t+1);r=util.format(r,n)}return{err:n,code:i,obj:s,msg:r}}static buildNestedErrorStackTrace(e,t){let n=e.stack;t&&(n+='\r\nCaused By -> '+t.stack),e.stack=n}toJSON(){return{error:this.name,errcode:this.code,message:this.message,stack:this.stack}}}class MissingConfigurationValueException extends Exception{constructor(e){super('Missing required configuration setting: `'+e+'`')}}class ApplicationNotCreatedException extends Exception{constructor(e){if(e){let t;t='symbol'==typeof e?e.toString():e,super(`Application not created. Please call 'CreateApplication' first before access '${t}'`)}else super(`Application not created. Please call 'CreateApplication' first`)}}class NotSupportedException extends Exception{constructor(e){super(`${e} is not support`)}}class DeserializationException extends Exception{constructor(e,t){super(e,{data:t},`Unable to parse giving json string`)}}class FileStreamException extends Exception{}class FileWriteException extends Exception{}class TransporterException extends Exception{}class LoggerException extends Exception{}class File{constructor(e,t){this._file=e,this._permission=t}static resolve(e,t,n){t=path.resolve(e,t);let i;try{i=fs.statSync(t)}catch(e){const n=new Error(`File '${t}' is not exist`);throw n.file=t,n.innerError=e,n}if(!i.isFile())throw new Error(`'${t}' is not a file`);try{fs.accessSync(t,n)}catch(e){throw e.file=t,e}return new File(t,n)}toString(){return this._file}get path(){return this._file}get permission(){return this._permission}readAll(){return fs.readFileSync(this._file,'utf8')}}File.Read=fs.constants.R_OK,File.ReadWrite=fs.constants.R_OK|fs.constants.W_OK,File.Write=fs.constants.W_OK;class Directory{constructor(e,t){this._directory=e,this._permission=t}static cwd(){return Directory.resolve(process.cwd(),'.',fs.constants.R_OK)}static withReadPermission(e){return Directory.resolve(process.cwd(),e,fs.constants.R_OK)}static withReadWritePermission(e){return Directory.resolve(process.cwd(),e,fs.constants.R_OK|fs.constants.W_OK)}static mkdir(e,t){const i=e.split(path.sep);let s=1,r=!1;for(;s++<i.length;){const e=i.slice(0,s).join(path.sep);try{fs.mkdirSync(e,t),r=!0}catch(t){let n;try{n=fs.statSync(e)}catch(e){throw t}if(!n.isDirectory())throw new Error(`'${e}' is not a directory`)}}return r}static resolve(e,t,n){t=path.resolve(e,t);let i;try{i=fs.statSync(t)}catch(e){const n=new Error(`Directory '${t}' is not exist`);throw n.file=t,n.innerError=e,n}if(!i.isDirectory()){const e=new Error(`'${t}' is not a directory`);throw e.file=t,e}try{fs.accessSync(t,n|fs.constants.X_OK)}catch(e){throw e.file=t,e}return new Directory(t,n)}toString(){return this._directory}get path(){return this._directory}directory(e){if(path.isAbsolute(e))throw new Error(`'${e}' is not a relative path`);return Directory.resolve(this._directory,e,this._permission)}file(e){if(path.isAbsolute(e))throw new Error(`'${e}' is not a relative path`);return File.resolve(this.path,e,this._permission)}}/*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */function __decorate(e,t,n,s){var o,a=arguments.length,l=3>a?t:null===s?s=Object.getOwnPropertyDescriptor(t,n):s;if('object'==typeof Reflect&&'function'==typeof Reflect.decorate)l=Reflect.decorate(e,t,n,s);else for(var g=e.length-1;0<=g;g--)(o=e[g])&&(l=(3>a?o(l):3<a?o(t,n,l):o(t,n))||l);return 3<a&&l&&Object.defineProperty(t,n,l),l}function __metadata(e,t){if('object'==typeof Reflect&&'function'==typeof Reflect.metadata)return Reflect.metadata(e,t)}class ConfigurationAttribute{constructor(e){this.key=e}beforeDecorate(){return!0}}function conf(e){return agentframework.decorateClassField(new ConfigurationAttribute(e))}class ApplicationSettings{constructor(){this.NAME='app',this.VERSION='0.0.0',this.ENV='production',this.PRINT_SETTINGS=!0,this.AUTO_CREATE_DIRECTORY=!0,this.PACKAGE_FILE='package.json',this.EXIT_WAIT_TIMEOUT=1e4,this.HOME_DIR='',this.DATA_DIR='',this.CONF_DIR='',this.LOG_DIR='',this.LOG_LEVEL='info',this.LOG_CONSOLE=!0,this.LOG_CONSOLE_LEVEL='debug',this.LOG_CONSOLE_STYLE='default',this.LOG_WEBHOOK=!1,this.LOG_WEBHOOK_LEVEL='error',this.LOG_WEBHOOK_URL=''}}__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'NAME',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'VERSION',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'ENV',void 0),__decorate([conf(),__metadata('design:type',Boolean)],ApplicationSettings.prototype,'PRINT_SETTINGS',void 0),__decorate([conf(),__metadata('design:type',Boolean)],ApplicationSettings.prototype,'AUTO_CREATE_DIRECTORY',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'PACKAGE_FILE',void 0),__decorate([conf(),__metadata('design:type',Number)],ApplicationSettings.prototype,'EXIT_WAIT_TIMEOUT',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'HOME_DIR',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'DATA_DIR',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'CONF_DIR',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_DIR',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_LEVEL',void 0),__decorate([conf(),__metadata('design:type',Boolean)],ApplicationSettings.prototype,'LOG_CONSOLE',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_CONSOLE_LEVEL',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_CONSOLE_STYLE',void 0),__decorate([conf(),__metadata('design:type',Boolean)],ApplicationSettings.prototype,'LOG_WEBHOOK',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_WEBHOOK_LEVEL',void 0),__decorate([conf(),__metadata('design:type',String)],ApplicationSettings.prototype,'LOG_WEBHOOK_URL',void 0);class ApplicationOptions{static parse(e){return e=e||{},e.root=e.root||process.cwd(),e.confDir=e.confDir||'conf',e.settings=e.settings||ApplicationSettings,e}}function padStart(e,t,n=' '){let i=e+'';if(i.length>=t)return i;n=n+'',0===n.length&&(n=' ');let s=t-i.length,r=Math.ceil(s/n.length),o=n.repeat(r).slice(0,s);return o+i}function padEnd(e,t,n=' '){if(e.length<t){const i=t-e.length;return e+n.repeat(i)}return e}class Printer{static printSettings(e,t){e.PRINT_SETTINGS&&(t.info('Active configuration properties:'),Object.getOwnPropertyNames(e).map(t=>{let n=e[t];const i=t.toUpperCase();if(i.endsWith('_URL')&&n.length){const e=new url.URL(n);e.password&&e.password.length&&(e.password=this.mask(e.password),n=e.toString())}else this.sensitive(i)&&(n=this.mask(n));return agentframework.IsObject(n)&&(n=util.inspect(n)),{key:t,value:n}}).forEach(e=>{t.info(`${e.key} = ${e.value}`)}))}static sensitive(e){return e.endsWith('_KEY')||e.endsWith('_PASSWORD')||e.endsWith('_SECRET')||e.endsWith('_TOKEN')}static mask(e){const t=e.length;let n='';for(let i=0;i<t;i++)n+=10<t&&(2>i||i>t-3)?e[i]:'*';return n}}const stopper=Symbol.for('stopPropagation');class StoppableEvent{stopPropagation(){this[stopper]=!0}isStopped(){return this[stopper]}}class StoppableEventException extends Exception{constructor(e,t,n){n?super(n,{stopped:e.isStopped()},t):super({stopped:e.isStopped()},t),Object.defineProperty(this,'event',{enumerable:!1,value:e})}}class StoppableEventEmitter extends events.EventEmitter{emitStoppableEvent(e,t){if(this.listenerCount(e)){const n=this.listeners(e);for(const e of n)if(e(t),t.isStopped())return!0}return!1}}(function(e){e[e.trace=10]='trace',e[e.debug=20]='debug',e[e.info=30]='info',e[e.warn=40]='warn',e[e.error=50]='error',e[e.fatal=60]='fatal'})(exports.LogLevel||(exports.LogLevel={}));class ConsoleFormatter{constructor(e){this.levels={10:['TRACE','grey'],20:['DEBUG','cyan'],30:['INFO ','green'],40:['WARN ','yellow'],50:['ERROR','magenta'],60:['FATAL','red']},this.textColors='none'!==e}static stylize(e,t='white'){const n=ConsoleFormatter.colors[t];return`\x1B[${n[0]}m${e}\x1B[${n[1]}m`}format(e){const t=[],n=[];let i=this.extractTime(e),s=this.extractLevel(e);const r=this.isSingleLineMsg(e);let o=r?this.extractMsg(e):'';r||t.push(this.indent(this.extractMsg(e)));const a=this.extractError(e);a&&t.push(this.indent(a)),this.applyDetails(this.extractCustomDetails(e),t,n);let l,d=n.length?' ('+n.join(', ')+')':'',g=t.length?t.join('\r\n\t----\r\n')+'\r\n':'';return this.textColors?(l=ConsoleFormatter.stylize(s[0],s[1]),10>=e.level?(i=ConsoleFormatter.stylize(i,'grey'),o=o&&ConsoleFormatter.stylize(o,'grey'),d=d&&ConsoleFormatter.stylize(d,'grey'),g=g&&ConsoleFormatter.stylize(g,'grey')):(i=ConsoleFormatter.stylize(i),d=d&&ConsoleFormatter.stylize(d,'cyan'),g=g&&ConsoleFormatter.stylize(g,'grey'))):l=s[0],`[${i}] ${l}: ${o}${d}\r\n${g}`}indent(e){return'\t'+e.split(/\r?\n/).join('\r\n\t')}extractTime(e){const t=e.time;if(agentframework.IsString(t)&&'T'===t[10]){const t=new Date(e.time);return t.toLocaleTimeString('zh-CN')+'.'+padStart(t.getMilliseconds(),3,'0')}else{const e=new Date;return e.toLocaleTimeString('zh-CN')+'.'+padStart(e.getMilliseconds(),3,'0')}}extractLevel(e){return this.levels[e.level]}isSingleLineMsg(e){return!agentframework.IsString(e.msg)||-1===e.msg.indexOf('\n')}extractMsg(e){return e.msg||''}extractError(e){if(e.stack)return e.stack}extractCustomDetails(e){const t=['level','time','msg','name','pid','hostname','v','src','err','error','client_req','client_res','req','res','stack','req_id'],n=[],i={};return Object.keys(e).filter(e=>-1===t.indexOf(e)).forEach(function(t){let s=e[t]||'',r=!1;'string'!=typeof s&&(s=JSON.stringify(s,null,2),r=!0),-1!==s.indexOf('\n')||50<s.length?n.push(t+': '+s):r||-1===s.indexOf(' ')&&0!==s.length?i[t]=s:i[t]=JSON.stringify(s)}),{details:n,extras:i}}applyDetails(e,t,n){e.details.forEach(e=>{t.push(this.indent(e))}),Object.keys(e.extras).forEach(t=>{n.push(t+'='+e.extras[t])})}}ConsoleFormatter.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]};const stringify=safeStringify;function parseYAML(e){return yaml.load(e.readAll())}function dumpYAML(e,t){fs.writeFileSync(t,yaml.dump(e))}function parseJSON(e){return JSON.parse(e.readAll())}function dumpJSON(e,t){fs.writeFileSync(t,JSON.stringify(e))}function deserialize(t){try{return JSON.parse(t)}catch(n){throw new DeserializationException(n,t)}}function serialize(e){if(null==e)return'null';else{const t=typeof e;return'boolean'==t?e?'"true"':'"false"':'number'==t||'function'==t||'symbol'==t?'"'+e.toString()+'"':stringify(e)}}class Transporter extends events.EventEmitter{constructor(e){super(),this.level=e}log(e,t){e<this.level||(e===exports.LogLevel.fatal?this.writeSync(t):this.write(t))}}class ConsoleLogTransporter extends Transporter{constructor(e,t){super(e),this.formatter=new ConsoleFormatter(t)}format(e){return this.formatter.format(deserialize(e))}write(e){process.stdout.write(this.format(e))}writeSync(e){fs.writeSync(2,this.format(e))}}class FileLogTransporter extends Transporter{constructor(e,t){super(e),this.filename=t,this.errors=[],this.openWritableFileStream()}openWritableFileStream(){const e=this,t=this.stream=fs.createWriteStream(this.filename,{flags:'a',encoding:'utf8'});t.on('open',function(t){e.fd=t}),t.on('error',function(t){const n=new FileStreamException(t);e.errors.push(n),e.emit('error',n)})}write(e){this.stream.write(e)}writeSync(e){try{this.fd?fs.writeSync(this.fd,e):fs.appendFileSync(this.filename,e)}catch(t){const n=new FileWriteException(t,{file:this.filename,fd:this.fd,transporter:this.constructor.name,data:e},'Unable to write log data');this.emit('error',n)}}}class Serializers{static req(e){return{method:e.method,url:e.url,headers:e.headers,remoteAddress:e.connection&&e.connection.remoteAddress,remotePort:e.connection&&e.connection.remotePort}}static res(e){return{statusCode:e.statusCode,header:e._header}}static error(e){return e.toJSON?e.toJSON():{error:e.name,stack:e.stack}}}class BaseLogger extends events.EventEmitter{context(){return this._context}trace(){this.compose(exports.LogLevel.trace,arguments)}debug(){this.compose(exports.LogLevel.debug,arguments)}log(){this.compose(exports.LogLevel.info,arguments)}info(){this.compose(exports.LogLevel.info,arguments)}warn(){this.compose(exports.LogLevel.warn,arguments)}error(){this.compose(exports.LogLevel.error,arguments)}fatal(){this.compose(exports.LogLevel.fatal,arguments)}compose(e,t){let n,i,s,r,o=t.length-1;for(n=0;n<=o;n++)if(!i&&t[n]instanceof Error)i=t[n];else if(!s&&'object'==typeof t[n])s=t[n];else{r=t[n];break}if(o>n){let e=Array.prototype.slice.call(t,n+1);r=util.format(r,e)}return this.write({level:e,msg:r,err:i,obj:s,seal:this._seal})}}class Logger extends BaseLogger{constructor(e,t){super(),this.options=e,this.transporters=t;const n=this;for(const i of t)i.on('error',function(e){n.emit('error',new TransporterException(e))});this._context=Object.assign(Object.create(null),e.context),this.makeSeal(this._context),this.cache=[],this.options.serializers=e.serializers||{},this.options.serializers=Object.assign({error:Serializers.error,res:Serializers.res,req:Serializers.req},e.serializers)}child(e){return new ChildLogger(this,Object.assign(Object.create(this._context),e))}update(e){'object'==typeof e&&(Object.assign(this._context,e),this.makeSeal(this._context))}write(e){let t=this.serialize(e);for(const n of this.transporters)n.log(e.level,t)}makeSeal(e){this._seal=','+JSON.stringify(e).slice(1,-1)+'}\r\n'}makeCache(e,t){const n=new Date(t);return'{"level":'+e+',"time":"'+n.toISOString()+'","msg":'}getCache(e){const t=Date.now();return this.cache[0]!==t&&(this.cache=[t,[]]),this.cache[1][e]?this.cache[1][e]:this.cache[1][e]=this.makeCache(e,t)}serialize(e){const t=this.options.serializers;let n=this.getCache(e.level)+serialize(e.msg);if(null!=e.err){let i=t.error(e.err);for(const e of Object.keys(i))n+=',"'+e+'":'+serialize(i[e])}if(null!=e.obj){let i=e.obj;i.toJSON?i=i.toJSON():i instanceof Error?i=t.error(i):i instanceof http.IncomingMessage?i=t.req(i):i instanceof http.OutgoingMessage&&(i=t.res(i));for(const e of Object.keys(i)){const s=i[e];n+=null==s?',"'+e+'":null':s.toJSON&&'function'==typeof s.toJSON?',"'+e+'":'+serialize(s.toJSON()):'req'===e?',"'+e+'":'+serialize(t.req(s)):'res'===e?',"'+e+'":'+serialize(t.res(s)):',"'+e+'":'+serialize(i[e])}}return n+e.seal}}class ChildLogger extends BaseLogger{constructor(e,t){super(),this.parent=e,this._context=t,this.makeSeal(this._context)}child(e){return new ChildLogger(this,Object.assign(Object.create(this._context),e))}update(e){this._context=Object.assign(this._context,e),this.makeSeal(this._context)}write(e){this.parent.write(e)}makeSeal(e){this._seal='';let t=e;const n=[];for(;t!==Object.prototype&&null!==t;)n.push(t),t=Object.getPrototypeOf(t);for(const t of n.reverse())for(const e of Object.keys(t))this._seal+=',"'+e+'":'+serialize(t[e]);this._seal+='}\r\n'}}function fatal(e){const t=new Date,n=t.toLocaleTimeString()+'.'+padStart(t.getMilliseconds(),3,'0');fs.writeSync(2,`[${n}] FATAL: ${e}\r\n`)}function CreateApplicationLogger(e){const t={context:{name:e.NAME,pid:process.pid,hostname:os.hostname(),v:0}},n=[];if(e.LOG_CONSOLE&&n.push(new ConsoleLogTransporter(exports.LogLevel[e.LOG_CONSOLE_LEVEL],e.LOG_CONSOLE_STYLE)),e.LOG_DIR){const t=path.join(e.LOG_DIR,'agent.log');n.push(new FileLogTransporter(exports.LogLevel[e.LOG_LEVEL],t))}const i=new Logger(t,n);return i.on('error',function(e){const t=new LoggerException(e);fatal(t.stack)}),i}class ExitEvent extends StoppableEvent{}var ApplicationEvents;(function(e){e.signals='signals',e.uncaughtException='uncaughtException',e.unhandledRejection='unhandledRejection',e.exiting='exiting',e.exit='exit'})(ApplicationEvents||(ApplicationEvents={}));function info(e){if(null==e)fs.writeSync(1,`\r\n`);else{const t=new Date,n=t.toLocaleTimeString()+'.'+padStart(t.getMilliseconds(),3,'0');fs.writeSync(1,`[${n}] INFO : ${e}\r\n`)}}function warn(e){const t=new Date,n=t.toLocaleTimeString()+'.'+padStart(t.getMilliseconds(),3,'0');fs.writeSync(1,`[${n}] WARN : ${e}\r\n`)}class Loader{constructor(e,t,n,i){this.env=e,this.root=t,this.conf=n,this._settings=i,this._settings.ENV=e,this._settings.HOME_DIR=t.path,this._settings.CONF_DIR=n.path}static loadSettings(e,t,n){info();const i=this.checkEnvironment(),s=e.directory(t),r=new Loader(i,e,s,n);return r.applyFileSettings('settings.yaml'),r.applyFileSettings(i+'.yaml'),r.applyFileSettings(i+'.local.yaml'),r.applyPackageInfo(),r.applyEnvironmentSettings(),r.resolveAbsolutePath(),r.resolveAbsoluteFile(),r.applyCustomSettingFile(),info(),r._settings}static checkEnvironment(){return process.env.NODE_ENV?info('\x1B[7mApplication loaded using the "'+process.env.NODE_ENV+'" configuration\x1B[0m'):(process.env.NODE_ENV='production',info('\x1B[33mNODE_ENV is not defined! Using default "'+process.env.NODE_ENV+'" configuration\x1B[0m')),process.env.NODE_ENV}applyFileSettings(e){let t,n;try{t=this.conf.file(e)}catch(e){return warn(`Application settings file '${e.file}' is not found, ignoring...`),!1}try{n=parseYAML(t)}catch(e){throw fatal(`Error parsing '${t.path}', reason: '${e.message}', exiting...`),e}if('object'!=typeof n){const e=new Error(`'${t.path}' is not validate settings file`);throw fatal(e.message),e}const i=[];for(const t of Object.keys(n))this._settings[t]=n[t],i.push(t);return info(`Applied ${i.length} key(s) from '${t.path}'`),!0}applyPackageInfo(){let e;try{e=this.root.file(this._settings.PACKAGE_FILE);try{const t=parseJSON(e);this._settings.VERSION=t.version||this._settings.VERSION,this._settings.NAME=t.name||this._settings.NAME}catch(e){warn(`Package file '${this._settings.PACKAGE_FILE}' parsing error, ignoring...`)}}catch(e){warn(`Package file '${e.file}' is not found, ignoring...`)}}applyEnvironmentSettings(){let e=!0;for(const t of Object.keys(this._settings)){const n=this._settings[t];if(null!=process.env[t]){info('Applying '+t+' from environment');try{this._settings[t]=JSON.parse(process.env[t])}catch(e){this._settings[t]=process.env[t]}}else null==n&&(e=!1,warn('Missing environment variable: '+t))}if(!e){const e=new Error('Prerequisite environment variable is missing, exiting...');throw fatal(e.message),e}}resolveAbsolutePath(){const e='_DIR',t=this._settings.AUTO_CREATE_DIRECTORY;t&&warn('Auto create directory is ON, all missing directory in the configuration will be created automatically.');for(const n of Object.keys(this._settings)){const i=this._settings[n];if(i&&i.length&&-1!==n.indexOf(e,n.length-e.length)&&i.split){const e=i.split(':'),s=e[0],r='rw'===e[1]?'rw':'ro',o=path.resolve(this.root.path,s);t&&Directory.mkdir(o)&&info(`Created directory '${o}'`),this._settings[n]='rw'==r?Directory.withReadWritePermission(o).path:Directory.withReadPermission(o).path}}}resolveAbsoluteFile(){const e='_FILE';for(const t of Object.keys(this._settings)){const n=this._settings[t];if(n&&n.length&&-1!==t.indexOf(e,t.length-e.length)&&n.split){const e=n.split(':'),i=e[0],s=e[1];this._settings[t]='rw'===s?File.resolve(this.root.path,i,fs.constants.R_OK|fs.constants.W_OK):'ro'===s?File.resolve(this.root.path,i,fs.constants.R_OK):path.resolve(this.root.path,i)}}}applyCustomSettingFile(){if(this._settings.DATA_DIR){const e=path.join(this._settings.DATA_DIR,'settings.json');let t={};if(fs.existsSync(e)){fs.accessSync(e,fs.constants.W_OK|fs.constants.R_OK);const n=fs.readFileSync(e,{encoding:'utf8'});try{t=JSON.parse(n)}catch(t){warn(`error parsing setting state file ${e}`)}for(const e of Object.keys(t))this._settings[e]=t[e]}}}}function CreateApplicationSettings(e,t,n){const i=Reflect.construct(n,[]);return Loader.loadSettings(e,t,i),i}class Updater{static updateSetting(t,e,n,i){if(!e.DATA_DIR)throw new Exception('Unable to update settings without config DATA_DIR');const s=path.join(e.DATA_DIR,'settings.json');let r={};if(fs.existsSync(s)){fs.accessSync(s,fs.constants.W_OK|fs.constants.R_OK);const e=fs.readFileSync(s,{encoding:'utf8'});try{r=JSON.parse(e)}catch(n){t.error(n,`error parsing setting state file ${s}`)}}r.hasOwnProperty(n)&&typeof r[n]!=typeof i&&t.error({origin:typeof r[n],new:typeof i},`Unable to update settings because type mismatch`),r[n]=i;const o=JSON.stringify(r,null,2);fs.writeFileSync(s,o,{encoding:'utf8',mode:420});const a=fs.readFileSync(s,{encoding:'utf8'}),l=JSON.parse(a);return l[n]}}class TypeRegistry{constructor(e){this.parent=e,this.initializers=new Map,this.finalizers=new Map}registerType(e,t,n){if('function'!=typeof e)throw new TypeError('Unable to register non-function type with a factory');if(this.initializers.has(e))throw new TypeError('Type already registered with a factory');if(t=t||e[TypeRegistry.Initializer],'function'!=typeof t)throw new TypeError('Unable to register non-function type as an initializer factory');if(this.initializers.set(e,t),n=n||e[TypeRegistry.Finalizer],n){if('function'!=typeof n)throw new TypeError('Unable to register non-function type as a finalizer factory');this.finalizers.set(e,n)}}deleteType(e){this.initializers.delete(e),this.finalizers.delete(e)}getInitializerOf(e){return this.initializers.get(e)||this.parent&&this.parent.getInitializerOf(e)}getFinalizerOf(e){return this.finalizers.get(e)||this.parent&&this.parent.getFinalizerOf(e)}}TypeRegistry.Singleton=Symbol('Singleton'),TypeRegistry.Initializer=Symbol('TypeInitializer'),TypeRegistry.Finalizer=Symbol('TypeFinalizer');class Resolver{constructor(e,t){this.singletons=new Map,this.types=new Map,this.constructorParams=e,this.registry=new TypeRegistry(t)}construct(e,t){if(t)return this.create(e,!0);let n=this.singletons.get(e);return n||(n=this.create(e,!0),this.singletons.set(e,n)),n}resolve(e,t){if(t)return Promise.resolve(this.create(e));let n=this.singletons.get(e);return n||(n=this.create(e),this.singletons.set(e,n)),Promise.resolve(n)}registerSingleton(e,t){if(this.singletons.has(e))throw new TypeError('Type already registered with a singleton instance');this.singletons.set(e,t)}releaseSingleton(e){this.singletons.delete(e)}registerType(e,t,n){this.registry.registerType(e,t,n),this.types.set(e,new Set)}releaseType(e){const t=[],n=this.registry.getFinalizerOf(e);if(!n)throw new TypeError(`No finalizer found for type ${e.prototype.constructor.name}`);const i=this.types.get(e);if(i)for(const s of i)t.push(Reflect.apply(n,e,[s,...this.constructorParams]));return this.registry.deleteType(e),this.types.delete(e),t}create(e,t){const n=this.registry.getInitializerOf(e);if(n){const i=Reflect.apply(n,e,this.constructorParams);if(i instanceof Promise){if(t)throw new Exception({type:e.prototype.constructor.name,initializer:n.name},`Factory method return a Promise which is not allowed to happen inside resolver.construct()`);return i.then(t=>{let n=this.types.get(e);return n||(n=new Set,this.types.set(e,n)),n.add(t),t})}return i}if('function'!=typeof e)throw new TypeError('Unable to construct non-function type');return Reflect.construct(e,this.constructorParams)}}class Application extends StoppableEventEmitter{constructor(e){super(),this._id=Date.now(),this._options=ApplicationOptions.parse(e),this._root=Directory.withReadPermission(this._options.root),this._settings=CreateApplicationSettings(this._root,this._options.confDir,this._options.settings),this._logger=CreateApplicationLogger(this._settings),this._resolver=new Resolver([this]),this._identity={id:'0',address:'/ip6/::0/tcp/0'},Printer.printSettings(this._settings,this._logger)}get name(){return this.settings.NAME}setIdentity(e){this._identity=e}get identity(){return this._identity}exit(e){this._logger.fatal(e);this.emitStoppableEvent(ApplicationEvents.exiting,new ExitEvent)||process.exit()}get root(){return this._root}directory(e=''){return this._root.directory(e)}file(e){return this._root.file(e)}get settings(){return this._settings}get(e,t){if(agentframework.IsNullOrUndefined(this._settings[e]))if(agentframework.IsNullOrUndefined(t))throw new MissingConfigurationValueException(e);else return t;return this._settings[e]}set(e,t){const n=Updater.updateSetting(this,this.settings,e,t);return this._settings[e]=n,n}has(e){return!agentframework.IsNullOrUndefined(this._settings[e])}child(){return this._logger.child.apply(this._logger,arguments)}update(){return this._logger.update.apply(this._logger,arguments)}context(){return this._logger.context()}trace(e,t,...n){this._logger.trace.apply(this._logger,arguments)}debug(e,t,...n){this._logger.debug.apply(this._logger,arguments)}log(e,t,...n){this._logger.log.apply(this._logger,arguments)}info(e,t,...n){this._logger.info.apply(this._logger,arguments)}warn(e,t,...n){this._logger.warn.apply(this._logger,arguments)}error(e,t,...n){this._logger.error.apply(this._logger,arguments)}fatal(e,t,...n){this._logger.fatal.apply(this._logger,arguments)}construct(e,t){return this._resolver.construct(e,t)}resolve(e,t){return this._resolver.resolve(e,t)}registerSingleton(e,t){return this._resolver.registerSingleton(e,t)}releaseSingleton(e){return this._resolver.releaseSingleton(e)}registerType(e,t,n){return this._resolver.registerType(e,t,n)}releaseType(e){return this._resolver.releaseType(e)}}class SingletonAttribute{constructor(e){this.type=e}beforeDecorate(){return!0}getInitializer(){return this}initialize(e,t){const n=t[0],i=this.type||e.design&&e.design.type;if(i===Object||!agentframework.IsFunction(i))throw new TypeError(`Invalid type to inject`);if(n&&'function'==typeof n.construct)return n.construct(this.type||e.design&&e.design.type);throw new TypeError(`Application container not found`)}}class TransitAttribute{constructor(e){this.type=e}beforeDecorate(){return!0}getInitializer(){return this}initialize(e,t){const n=t[0],i=this.type||e.design&&e.design.type;if(i===Object||!agentframework.IsFunction(i))throw new TypeError(`Invalid type to inject`);if(n&&'function'==typeof n.construct)return n.construct(this.type||e.design&&e.design.type,!0);throw new TypeError(`Application container not found`)}}class ServiceAttribute{beforeDecorate(){return!0}}function service(){return agentframework.decorateAgent(new agentframework.AgentAttribute({features:11}),void 0,[new ServiceAttribute])}function singleton(e){return agentframework.decorateClassField(new SingletonAttribute(e))}function transit(e){return agentframework.decorateClassField(new TransitAttribute(e))}class Resolvable{constructor(e){this.settings=e.settings,this.logger=e.child({cn:this.name}),this.logger.debug(`Creating new instance`)}get name(){return this.constructor.prototype.constructor.name}}class Middleware extends Array{use(e){this.push(e)}next(e,t,n){let i,s=!1;if(!(n>this.length))return i=this[n]||t,i&&i(e,()=>{if(s)throw new Error('next() called multiple times');s=!0;const i=this.next(e,t,n+1);return Promise.resolve(i)})}compose(e,t){try{return Promise.resolve(this.next(e,t,0))}catch(e){return Promise.reject(e)}}}const STAR=42,SLASH=47,COLON=58;(function(e){e[e.STATIC=0]='STATIC',e[e.PARAM=1]='PARAM',e[e.ANY=2]='ANY'})(exports.RouteType||(exports.RouteType={}));class Route{constructor(e='',t=exports.RouteType.STATIC,n=[],i=Object.create(null)){this.prefix=e,this.key=e.charCodeAt(0),this.type=t,this.children=n,this.data=i}node(e){let t=e.length;const n=[];for(let s=0;s<t;++s){const i=e.charCodeAt(s);if(i===COLON){const i=s+1;for(this.ensureChild(e.substring(0,s),exports.RouteType.STATIC);s<t&&e.charCodeAt(s)!==SLASH;)s++;if(n.push(e.substring(i,s)),e=e.substring(0,i)+e.substring(s),s=i,t=e.length,s===t)return this.ensureChild(e.substring(0,s),exports.RouteType.PARAM).setParams(n);this.ensureChild(e.substring(0,s),exports.RouteType.PARAM)}else if(i===STAR)return this.ensureChild(e.substring(0,s),exports.RouteType.STATIC),n.push('*'),this.ensureChild(e.substring(0,t),exports.RouteType.ANY).setParams(n)}return this.ensureChild(e,exports.RouteType.STATIC).setParams(n)}search(e){const t=[],n=this.findChild(e,t);if(!n)return null;const s=t.length,r=Object.create(null);if(n.parts)for(let e=0;e<s;++e)r[n.parts[e]]=t[e];return{node:n,params:r}}ensureChild(e,t){let n,i,s,r,o,a=this;const d=a.findOwnChildWithLabel(e.charCodeAt(0));if(d)a=d;else return a.createChild(e,t);for(;;){for(n=a.prefix,i=e.length,s=n.length,r=0,o=i<s?i:s;r<o&&e.charCodeAt(r)===n.charCodeAt(r);)r++;if(r<s){const s=new Route(n.substring(r),a.type,a.children,a.data);return a.parts&&a.parts.length&&s.setParams(a.parts),a.prefix=n.substring(0,r),a.type=exports.RouteType.STATIC,a.children=[s],a.data=Object.create(null),r==i?a:a.createChild(e.substring(r),t)}if(r<i){e=e.substring(r);const n=a.findOwnChildWithLabel(e.charCodeAt(0));if(null!=n){a=n;continue}return a.createChild(e,t)}return a}}createChild(e,t){const n=new Route(e,t);return this.children.push(n),n}setParams(e){return this.parts=e.slice(0),this}findChild(e,t){const n=this,i=e.length,s=n.prefix;if(0===i||e===s)return n;const r=s.length;let o=0;for(const n=i<r?i:r;o<n&&e.charCodeAt(o)===s.charCodeAt(o);)o++;o===r&&(e=e.substring(o));const a=n.findOwnChild(e.charCodeAt(0),exports.RouteType.STATIC);if(a){const n=a.findChild(e,t);if(n)return n}if(o!==r)return null;const d=n.findOwnChildByType(exports.RouteType.PARAM);if(d){o=e.length;let n=0;for(;n<o&&e.charCodeAt(n)!==SLASH;)n++;t.push(e.substring(0,n));const i=d.findChild(e.substring(n),t);if(i)return i;t.pop()}const g=n.findOwnChildByType(exports.RouteType.ANY);if(g){t.push(e);const n=g.findChild('',t);if(n)return n}return null}findOwnChild(e,t){for(let n=0,i=this.children.length;n<i;n++){const i=this.children[n];if(e===i.key&&t===i.type)return i}return null}findOwnChildWithLabel(e){for(let t=0,n=this.children.length;t<n;t++){const n=this.children[t];if(e===n.key)return n}return null}findOwnChildByType(e){for(let t=0,n=this.children.length;t<n;t++){const n=this.children[t];if(e===n.type)return n}return null}}class BaseX{constructor(e){this.map={},this.alphabet=e,this.base=e.length,this.leader=e.charAt(0);for(let t,n=0;n<e.length;n++){if(t=e.charAt(n),void 0!==this.map[t])throw new TypeError(t+' is ambiguous');this.map[t]=n}}static get singleton(){const e=this[TypeRegistry.Singleton],t=e?e():Reflect.construct(this,[]);return Reflect.defineProperty(this,'singleton',{value:t}),t}fromBuffer(e){if(0===e.length)return'';const t=[0];for(let n,s=0;s<e.length;++s){n=e[s];for(let e=0;e<t.length;++e)n+=t[e]<<8,t[e]=n%this.base,n=0|n/this.base;for(;0<n;)t.push(n%this.base),n=0|n/this.base}let n='';for(let t=0;0===e[t]&&t<e.length-1;++t)n+=this.leader;for(let i=t.length-1;0<=i;--i)n+=this.alphabet[t[i]];return n}toBuffer(e){let t=this.decodeUnsafe(e);if(t)return t;throw new Error('Non-base'+this.base+' character')}fromHex(e){return 1==e.length%2&&(e='0'+e),this.fromBuffer(Buffer.from(e,'hex'))}toHex(e){return this.toBuffer(e).toString('hex')}fromNumber(e){var t=Math.floor;if(isNaN(+e)||null===e||e===Number.POSITIVE_INFINITY)throw'The input is not valid';if(0>e)throw new Error('Can\'t represent negative numbers now');let n,i=t(e),s='';for(;n=i%this.base,s=this.alphabet.charAt(n)+s,i=t(i/this.base),0!=i;);return s}toNumber(t){let n=0;for(let i=0;i<t.length;i++)n=64*n+ +this.map[t.charAt(i)];return n}decodeUnsafe(e){if('string'!=typeof e)throw new TypeError('Expected String');if(0===e.length)return Buffer.allocUnsafe(0);let t=[0];for(let n,s=0;s<e.length;s++){if(n=this.map[e[s]],void 0===n)throw new Error(`Unknown character ${e[s]} to decode`);let i=n;for(let e=0;e<t.length;++e)i+=t[e]*this.base,t[e]=255&i,i>>=8;for(;0<i;)t.push(255&i),i>>=8}for(let n=0;e[n]===this.leader&&n<e.length-1;++n)t.push(0);return Buffer.from(t.reverse())}}class Base62 extends BaseX{constructor(){super('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')}static fromBuffer(e){return this.singleton.fromBuffer(e)}static toBuffer(e){return this.singleton.toBuffer(e)}static fromHex(e){return this.singleton.fromHex(e)}static toHex(e){return this.singleton.toHex(e)}static fromNumber(e){return this.singleton.fromNumber(e)}static toNumber(e){return this.singleton.toNumber(e)}}class Base58 extends BaseX{constructor(){super('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')}static fromBuffer(e){return this.singleton.fromBuffer(e)}static toBuffer(e){return this.singleton.toBuffer(e)}static fromHex(e){return this.singleton.fromHex(e)}static toHex(e){return this.singleton.toHex(e)}static fromNumber(e){return this.singleton.fromNumber(e)}static toNumber(e){return this.singleton.toNumber(e)}}function retry(e,t={retries:3,factor:3,minTimeout:1e3,maxTimeout:6e4,randomize:!0}){return new Promise((n,i)=>{const s=retrier.operation(t),r=e=>{i(e||new Error('Aborted'))},o=e=>{s.retry(e)||i(s.mainError())};s.attempt(t=>{let i;try{i=e(r,t,s.errors())}catch(e){return o(e)}i&&agentframework.IsFunction(i.then)?i.then(n,o):n(i)})})}class Identity{}const globalKey=Symbol.for('agentstack.global');function CreateApplication(e){return global[globalKey]=new Application(e)}function SetCurrentApplication(e){global[globalKey]=e}function CurrentApplication(){return global[globalKey]}function CreateApplicationProxy(){return new Proxy(Object.create(Application.prototype),{setPrototypeOf:function(){throw new NotSupportedException('setPrototypeOf')},isExtensible:function(){const e=global[globalKey];if(agentframework.IsNullOrUndefined(e))throw new ApplicationNotCreatedException;return Reflect.isExtensible(e)},preventExtensions:function(){throw new NotSupportedException('deleteProperty')},getOwnPropertyDescriptor:function(e,t){const n=global[globalKey];if(agentframework.IsNullOrUndefined(n))throw new ApplicationNotCreatedException;return Reflect.getOwnPropertyDescriptor(n,t)},has:function(e,t){const n=global[globalKey];return!agentframework.IsNullOrUndefined(n)&&Reflect.has(n,t)},get:function(e,t){const n=global[globalKey];if(agentframework.IsNullOrUndefined(n))throw new ApplicationNotCreatedException(t);return n[t]},set:function(e,t,n){throw new NotSupportedException('set '+util.inspect(t)+' = '+util.inspect(n))},deleteProperty(e,t){throw new NotSupportedException('deleteProperty '+util.inspect(t))},defineProperty(e,t,n){throw new NotSupportedException('defineProperty '+util.inspect(t)+' as '+util.inspect(n))},ownKeys(){const e=global[globalKey];if(agentframework.IsNullOrUndefined(e))throw new ApplicationNotCreatedException;return Object.keys(e)}})}const Signals={SIGHUP:1,SIGINT:2,SIGQUIT:3,SIGTERM:15};class SignalEvent extends StoppableEvent{constructor(e,t){super(),this.signal=e,this.code=t}}class UnhandledSignalException extends StoppableEventException{constructor(e,t,n){super(e,`Received signal '${t}' and now exiting...`),this.code=n}}function GenerateSignalHandlers(t,n){return function(){const i=Signals[n];if(t&&Reflect.has(t,'settings')){const s=new SignalEvent(n,i);if(t.emitStoppableEvent(ApplicationEvents.signals,s))return;t.exit(new UnhandledSignalException(s,n,i))}else fatal(`Received signal '${n}' and no application been created. exiting...\r\n`),setImmediate(function(){process.exit(i)})}}class UncaughtExceptionEvent extends StoppableEvent{constructor(e){super(),this.exception=e}}class UnhandledException extends StoppableEventException{constructor(e,t){super(e,`Received UncaughtException and now exiting...`,t)}}function GenerateUncaughtExceptionHandlers(t){return function(n){if(t&&Reflect.has(t,'settings')){const i=new UncaughtExceptionEvent(n);if(t.emitStoppableEvent(ApplicationEvents.uncaughtException,i))return;t.exit(new UnhandledException(i,n))}else fatal(`Application [null] exiting...\r\n${n.stack}\r\n`),setImmediate(function(){process.exit(1102)})}}function GenerateExitHandlers(e){return function(t){if(e&&Reflect.has(e,'settings')){const n=e.settings.NAME;0<t?e.fatal(`Application [${n}] exited with code ${t}`):e.info(`Application [${n}] exited successfully`)}else 0<t?fatal(`Application exited with code ${t}`):info(`Application exited successfully`)}}let listeners;function PrepareEvents(e){const t=new Map;for(const n of Object.keys(Signals))t.set(n,GenerateSignalHandlers(e,n));return t.set(ApplicationEvents.uncaughtException,GenerateUncaughtExceptionHandlers(e)),t.set(ApplicationEvents.exit,GenerateExitHandlers(e)),t}function RegisterEvents(e){listeners||(listeners=PrepareEvents(e));for(const[t,n]of listeners.entries())process.on.call(process,t,n);return e}var index=RegisterEvents(CreateApplicationProxy());exports.URL=url.URL,exports.default=index,exports.Exception=Exception,exports.FileStreamException=FileStreamException,exports.TransporterException=TransporterException,exports.LoggerException=LoggerException,exports.MissingConfigurationValueException=MissingConfigurationValueException,exports.ApplicationNotCreatedException=ApplicationNotCreatedException,exports.NotSupportedException=NotSupportedException,exports.Application=Application,exports.ApplicationSettings=ApplicationSettings,exports.conf=conf,exports.ConfigurationAttribute=ConfigurationAttribute,exports.parseJSON=parseJSON,exports.parseYAML=parseYAML,exports.dumpJSON=dumpJSON,exports.dumpYAML=dumpYAML,exports.deserialize=deserialize,exports.serialize=serialize,exports.service=service,exports.singleton=singleton,exports.transit=transit,exports.Resolver=Resolver,exports.Resolvable=Resolvable,exports.TypeRegistry=TypeRegistry,exports.Middleware=Middleware,exports.Route=Route,exports.Directory=Directory,exports.File=File,exports.BaseX=BaseX,exports.Base62=Base62,exports.Base58=Base58,exports.retry=retry,exports.Identity=Identity,exports.CreateApplication=CreateApplication,exports.CurrentApplication=CurrentApplication,exports.SetCurrentApplication=SetCurrentApplication,exports.padStart=padStart,exports.padEnd=padEnd; //# sourceMappingURL=index.js.map