sumor 1.0.2 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
global.globalRequire = (path)=>{return require(path);};/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(()=>(()=>{var e={525:e=>{e.exports=__dirname},167:e=>{"use strict";e.exports=require("axios")},147:e=>{"use strict";e.exports=require("fs")}},t={};function n(r){var s=t[r];if(void 0!==s)return s.exports;var a=t[r]={exports:{}};return e[r](a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{"use strict";n.d(r,{default:()=>Lt});const e=require("express");var t=n.n(e);const s=require("uuid");var a=n.n(s);const o=()=>a().v4().replace(/-/g,""),i=require("stream");var c=n.n(i);const l=e=>{let t,n=e;return"string"==typeof e?t=Buffer.from(e):Buffer.isBuffer(e)&&(t=e),t&&(n=new(c().PassThrough),n.end(t)),n};function u(e){return new Promise(((t,n)=>{let r=[];e.on("error",n),e.on("data",(e=>r.push(e))),e.on("end",(()=>t(Buffer.concat(r))))}))}const m=async(e,t)=>{if(e){let n,r;switch(t=t||"stream"){case"string":r=await u(e),n=r.toString();break;case"buffer":n=await u(e);break;default:n=e}return n}return e},p={delay:async e=>new Promise((t=>{setTimeout((()=>{t()}),1e3*e)})),uuid:o,stream:{from:m,to:l},number:{from10to36:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyz".split(""),n=t.length;let r=+e;const s=[];do{let e=r%n;r=(r-e)/n,s.unshift(t[e])}while(r);return s.join("")},from10to62:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ".split(""),n=t.length;let r=+e;const s=[];do{let e=r%n;r=(r-e)/n,s.unshift(t[e])}while(r);return s.join("")},from62to10:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ",n=t.length;let r=(e=String(e)).length,s=0,a=0;for(;s<r;)a+=Math.pow(n,s++)*t.indexOf(e.charAt(r-s)||0);return a},from36to10:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyz",n=t.length;let r=(e=String(e)).length,s=0,a=0;for(;s<r;)a+=Math.pow(n,s++)*t.indexOf(e.charAt(r-s)||0);return a}}},d=require("fs-extra");var g=n.n(d);const h=(e,t)=>(n,r,s)=>{let a,o;if(r=r||{},""!==(s=s||t)){const e=s.split("-");a=e[0],o=e[1]}if(n){const t=n.split("."),i=t.pop(),c=t.join(".");let l;return e[c]&&(o&&(l=(e[c][s]||{})[i]),!l&&a&&(l=(e[c][a]||{})[i]),l||(l=(e[c][""]||{})[i])),((e,t)=>{t=t||{};const n=(e=e||"").match(new RegExp(/\${.*?}/,"g"));if(n)for(let r of n){const n=t[r.substr(2,r.length-3)]||"";e=e.replace(r,n)}return e})(l,r)}{const t={};for(let n in e){const r=e[n][""]||{};let i={},c={};a&&(i=e[n][a]||{}),o&&(c=e[n][s]||{});const l=Object.assign({},r,i,c);for(let e in l)t[`${n}.${e}`]=l[e]}return t}},w=require("chalk");var f=n.n(w);const y={trace:"#7f8c8d",debug:"#2980b9",info:"#2ecc71",warn:"#f39c12",error:"#c0392b"};let _="debug",$=!1;const E=class{constructor(e,t){e=e||"DEFAULT";const n=["trace","debug","info","warn","error"];for(let r of n)this[r]=function(){const n=Array.from(arguments),s=["#",(new Date).toISOString(),r.toUpperCase(),e.toUpperCase()];t&&""!==t&&s.push(t),s.push("-");const a=`${s.join(" ")}`;$?n.unshift(a):n.unshift(f().hex(y[r]).visible(a)),console.log.apply(null,n)}}static setProduction(e){e&&($=!!e)}static setLevel(e){e&&(_=e)}static getLevel(){return _}};let S=0;const v=require("os");var T=n.n(v);const x=1e3*(Math.floor(Date.now()/1e3)-T().uptime()),b=Date.now(),O=e=>Math.round(e),N={serverUpTime:x,serviceUpTime:b,interval:60,memory:[],cpu:[]};let I;const k=async()=>{N.updateTime=Date.now();const e={time:Date.now(),idle:T().cpus().map((e=>e.times.idle))};if(I){const t=((e,t)=>{const n=t.time-e.time;let r=0;for(let s in t.idle){let a=(t.idle[s]-e.idle[s])/n;a>1&&(a=1),a=100-100*a,r+=a}return O(r/t.idle.length)})(I,e);N.cpu.unshift(t),N.cpu=N.cpu.slice(0,1440)}I=e,N.memory.unshift(O((T().totalmem()-T().freemem())/T().totalmem()*100)),N.memory=N.memory.slice(0,1440)},R=require("body-parser");var D=n.n(R);const A=require("multer");var L=n.n(A);const C=require("cookie-parser");var q=n.n(C);const F=require("knex");var P=n.n(F);const j=e=>{const t={};switch((e=e||{}).type=e.type||"better-sqlite3",e.type){case"sqlite":case"sqlite3":case"better-sqlite3":t.client="better-sqlite3";break;case"mysql":case"mysql2":t.client="mysql2";break;default:throw new Error(`不支持数据库类型${e.type}`)}switch(t.client){case"better-sqlite3":t.connection={filename:e.path||process.cwd()+"/main.sqlite"},t.useNullAsDefault=!0;break;case"mysql2":t.connection={host:e.host,port:e.port||3306,user:e.user,password:e.password,database:e.database,charset:e.charset||"utf8mb4"},t.pool=e.pool||{min:2,max:10}}return t};class z{constructor(e,t){this.config=e,this._config=j(e),this._logger=t||{debug:console.log,trace:console.log}}async ensure(){let e,t,n,r,s;switch(this._config.client){case"better-sqlite3":await g().ensureFile(this._config.connection.filename);break;case"mysql2":e=Object.assign({},this.config),t=e.database,delete e.database,n=P()(j(e)),r=await n.raw("show databases"),s=!!r[0].filter((e=>e.Database===t))[0],s||(this._logger.trace("数据库不存在,正在创建"),await n.raw(`CREATE DATABASE IF NOT EXISTS ${t} default charset utf8mb4 COLLATE utf8mb4_general_ci`),this._logger.trace("数据库创建完成")),await new Promise((e=>{n.destroy((function(){e()}))}));break;default:this._logger.trace(`暂不支持${this._config.client}类型数据库创建,请自行确认数据库存在`)}}async connect(){this.knex||(this.knex=P()(this._config))}async destroy(){this.knex&&(await new Promise((e=>{this.knex.destroy((function(){e()}))})),delete this.knex)}}const M=(e,t)=>{t=t||"-";const n=[];for(let t=0;t<e.length;t++){const s=e.charAt(t),a=s.toLowerCase();0===n.length?n.push(a):((r=s)>="A"&&r<="Z"&&n.push(""),n[n.length-1]=n[n.length-1]+=a)}var r;return n.join(t)},B=(e,t,n,r)=>{let s;switch(n.type=n.type||"string",n.type){case"string":n.length=n.length||255;break;case"number":n.length=n.length||10}if(n.increment)s=e.increments(t);else{let r;switch((e=>{const t=e.length;let n;switch(e.type){case"string":n=t>1e3?"text":"string";break;case"number":n=t>18?"string":null!==e.scale&&void 0!==e.scale?"double":t>9?"bigInteger":t>4?"integer":t>2?"smallint":"tinyint"}return n})(n)){case"tinyint":s=e.tinyint(t),r="number";break;case"smallint":s=e.smallint(t),r="number";break;case"integer":s=e.integer(t),r="number";break;case"bigInteger":s=e.bigInteger(t),r="number";break;case"string":s=e.string(t,n.length),r="string";break;case"text":s=e.text(t,n.length),r="string";break;case"double":s=e.double(t,n.length,n.scale),r="number"}if(null!==n.default){let e;"number"===r?(void 0===n.default&&(n.default=0),e=parseInt(n.default,10)):(void 0===n.default&&(n.default=""),e=n.default.toString()),s.defaultTo(e)}n.notNull&&s.notNullable()}n.key&&s.primary(),r&&s.alter()},H=async(e,t,n)=>{n=n||{};const r={},s=await e.schema.hasTable(t).transacting(e);if(!n.rename&&!n.deleted){let e=!1;for(let t in n.property)n.property[t].key&&(e=!0);e||(r.id={type:"string",length:32});for(let t in n.property)"id"!==t||e?["createdBy","createdTime","updatedBy","updatedTime"].indexOf(t)<0&&(r[t]=n.property[t]):r[t]=n.property[t];let t={type:"number",length:13};if(n.join)for(let e in n.join)r[M(e,"_")+"_id"]={type:"string",length:32};r.createdBy={name:"创建者",type:"string",length:32},r.createdTime={name:"创建时间",...t},r.updatedBy={name:"更新者",type:"string",length:32},r.updatedTime={name:"更新时间",...t}}if(s)if(n.rename){const r=M(n.rename,"_");await e.schema.renameTable(t,r)}else if(n.deleted)await e.schema.dropTable(t);else{let n=await e(t).columnInfo();await e.schema.alterTable(t,(function(e){for(let t in r){const s=M(t,"_"),a=r[t];if(n[s]&&a.rename){const t=M(a.rename,"_");e.renameColumn(s,t)}}})).transacting(e),n=await e(t).columnInfo(),await e.schema.alterTable(t,(function(e){for(let t in r){const s=M(t,"_"),a=r[t];a.rename||(n[s]?a.deleted?e.dropColumn(s):B(e,s,a,!0):a.rename||a.deleted||B(e,s,a))}}))}else n.rename||n.deleted||await e.schema.createTable(t,(function(e){for(let t in r){const n=M(t,"_"),s=r[t];s.rename||s.deleted||B(e,n,s)}})).transacting(e)},U=(e,t,n)=>{t=t||"-";let r=(e=e.toLowerCase()).split(t);e="";for(let t in r){let n=r[t];e+=n.replace(n[0],n[0].toUpperCase())}return n&&(e=e.replace(e[0],e[0].toLowerCase())),e},G=e=>{let t=typeof e;if(null===e)t="null";else if("object"===t){const n=Object.prototype.toString.call(e);"[object Array]"===n?t="array":"[object RegExp]"===n&&(t="regexp")}return t},J=e=>{const t={};for(let n in e)t[M(n,"_")]=e[n];return t},K=async({config:e,logger:t})=>{t=t||{debug:console.log,trace:console.log};const n=new z(e,t);await n.ensure(),await n.connect();const r={info:{}};return{connect:async(e,t)=>((e,t,n,r)=>{r=r||"";const s={};let a;const i=async function(){a||(a=await e.knex.transaction())};return s.setUser=e=>{r=e,n.trace(`已修改操作用户为${e}`)},s.info=async(e,n)=>{if(!n&&t.info[e])return t.info[e];const r=await a.from(e).columnInfo(),s={};for(let e in r){const t=U(e,"_",!0);let n;switch(r[e].type){case"char":case"varchar":case"text":case"mediumtext":case"":n="string";break;case"tinyint":case"smallint":case"int":case"integer":case"bigint":case"float":case"double":n="number";break;default:n="string",console.log(`未知数据类型 ${e} ${JSON.stringify(r[e])}`)}s[t]={type:n,length:parseInt(r[e].maxLength,10)}}return t.info[e]=s,s},s.count=async(e,t,r)=>{await i(),r=r||{},e=M(e,"_");const s=a.from(e);s.count({count:"*"});let o=!1;if(t){t=J(t);for(let e in t)if("object"===G(t[e]))for(let n in t[e]){const r=n,a=t[e][n];"<>"===r&&null===a?s.whereNotNull(e):s.where(e,r,a)}else null===t[e]?s.whereNull(e):s.where(e,t[e]);o=!0}if(r.term&&""!==r.term&&r.termRange)for(let e in r.termRange){const t=r.termRange[e];0===parseInt(e)?o?s.andWhere(t,"like",`%${r.term}%`):(s.where(t,"like",`%${r.term}%`),o=!0):s.orWhere(t,"like",`%${r.term}%`)}return n.trace(s.toSQL().sql,s.toSQL().bindings),(await s)[0].count},s.single=async(e,t,n)=>{(n=n||{}).top=1;const r=await s.select(e,t,n);return r.length,r[0]},s.select=async(e,t,r)=>{n.trace(`查询${e},条件${JSON.stringify(t)},参数${JSON.stringify(r)}`),await i(),r=r||{},e=M(e,"_");const o=await s.info(e),c=a.from(e);let l=r.field;l&&(l=l.map((e=>M(e,"_")))),c.select(l);let u=!1;if(t){t=J(t);for(let e in t)if("object"===G(t[e]))for(let n in t[e]){const r=n,s=t[e][n];"<>"===r&&null===s?c.whereNotNull(e):c.where(e,r,s)}else null===t[e]?c.whereNull(e):c.where(e,t[e]);u=!0}if(r.term&&""!==r.term&&r.termRange)for(let e in r.termRange){const t=r.termRange[e];0===parseInt(e)?u?c.andWhere(t,"like",`%${r.term}%`):(c.where(t,"like",`%${r.term}%`),u=!0):c.orWhere(t,"like",`%${r.term}%`)}if(!r.sort&&o.createdTime&&(r.sort="created_time DESC"),r.sort)if("string"==typeof r.sort){const e=r.sort.split(",");for(let t in e){let n=e[t].trim();n=n.split(" "),n[0]=M(n[0],"_"),e[t]=n.join(" ")}c.orderByRaw(e.join(","))}else c.orderBy(r.sort);return r.top&&c.limit(r.top),r.skip&&c.offset(r.skip),n.trace(c.toSQL().sql,c.toSQL().bindings),(await c).map((e=>(e=>{const t={};for(let n in e)t[U(n,"_",!0)]=e[n];return t})(e)))},s.insert=async(e,t)=>{t=t||{},e=M(e,"_"),await i();const c=async()=>{const t=o();return 0!==await s.count(e,{id:t})?await c():t};t.id||(t.id=await c()),t.createdBy=r||"",t.createdTime=Date.now(),t.updatedBy=r||"",t.updatedTime=Date.now(),t=J(t);const l=a.insert(t).into(e);return n.trace(l.toSQL().sql,l.toSQL().bindings),await l,t.id},s.update=async(e,t)=>{t=t||{},e=M(e,"_"),await i();const s=t.id;if(delete t.id,null==s)throw new Error("数据ID不存在,无法找到要更新的数据");t.updatedBy=r||"",t.updatedTime=Date.now(),t=J(t);const o=a.update(t).from(e).where({id:s});n.trace(o.toSQL().sql,o.toSQL().bindings),await o},s.modify=async(e,t,r)=>{n.trace(`强制修改${e},数据${JSON.stringify(r)},检查字段${JSON.stringify(t)}`),e=M(e,"_");const a={};for(let e of t)a[M(e,"_")]=r[e];const o=await s.single(e,a,{field:["id"]});let i;return o?(i=o.id,r.id=i,await s.update(e,r)):i=await s.insert(e,r),i},s.ensure=async(e,t,r)=>{n.trace(`确保${e}存在数据${JSON.stringify(r)},检查字段${JSON.stringify(t)}`),e=M(e,"_");const a={};for(let e of t)a[M(e,"_")]=r[e];const o=await s.select(e,a,{field:["id"]});let i;return i=o[0]?o[0].id:await s.insert(e,r),i},s.delete=async(e,t)=>{e=M(e,"_");const r=a.from(e);return t&&(t=J(t),r.where(t)),n.trace(r.toSQL().sql,r.toSQL().bindings),await r.del()},s.sql=async(e,t)=>(await i(),await a.raw(e,t)),s.commit=async()=>{if(a)try{await a.commit(),a=null}catch(e){n.error(e)}},s.rollback=async()=>{if(a)try{await a.rollback(),a=null}catch(e){n.error(e)}},s})(n,r,e,t),destroy:async()=>{await n.destroy()}}},W=async({config:e,logger:t,entity:n,view:r})=>{t=t||{debug:console.log,trace:console.log};const s=new z(e,t);await s.ensure(),await s.connect();const a=await s.knex.transaction();try{for(let e in n){const r=M(e,"_");t.debug(`正在安装实体${e}为${r}`),await H(a,r,n[e]),t.debug(`正在安装实体${e}完成`)}for(let e in r){const t=M(e,"_");await a.schema.dropViewIfExists(t)}const e=((e,t)=>{t=!!t;const n={};for(let t in e)n[M(t,"_")]=e[t];const r=(e=>{let t={};for(let n in e)t[n]=e[n].sql;return t})(n),s=(e=>{let t={};const n=t=>{if(0===e[t].length)return 1;{let r=1;for(let s in e[t])r+=n(e[t][s]);return r}};for(let r in e)t[r]=n(r);return t})((e=>{let t={};for(let n in e){t[n]=[];for(let r in e){let s=e[r].toLowerCase();s=s.replace(/`/g,""),s=s.replace(/\n/g," "),s=s.replace(/ {2}/g," "),s=s.replace(/ {2}/g," "),s=s.replace(/ {2}/g," "),(s.indexOf(` from ${n} `)>=0||s.indexOf(` join ${n} `)>=0)&&t[n].push(r)}}let n={};for(let r in e){n[r]=[];for(let e in t)t[e].indexOf(r)>=0&&n[r].push(e)}return n})(r)),a=((e,t)=>{let n=[];for(let t in e)n.push({name:t,index:e[t]});n=n.sort(((e,t)=>e.index>t.index?1:-1)),t&&(n=n.reverse());let r=[];for(let e in n)r.push(n[e].name);return r})(s,t);let o={};for(let e in a)o[U(a[e],"_")]=n[a[e]];return o})(r);for(let n in e){const r=M(n,"_");t.debug(`正在安装视图${n}为${r}`),await a.schema.createViewOrReplace(r,(function(t){t.as(e[n].sql)})),t.debug(`正在安装视图${n}完成`)}await a.commit()}catch(e){await a.rollback()}await s.destroy()},Z=async(e,t)=>{let n;if("redis"===(e.type||"sqlite")){const e={};n=t=>({get:async(t,n)=>(e[t]||{})[n],set:async(t,n,r)=>{e[t]=e[t]||{},e[t][n]=r}})}else{await W({config:e,logger:t,entity:{cache:{property:{namespace:{type:"string",length:100,notNull:!0},key:{type:"string",length:500,notNull:!0},value:{type:"string",length:1e4,notNull:!0}}}}});const r=await K({config:e,logger:t});n=e=>({get:async(t,n)=>{const s=await r.connect(e),a=await s.single("cache",{namespace:t,key:n});if(await s.commit(),a)return e.trace(`读取缓存${t} ${n}。数据为${a.value}`),a.value;e.trace(`读取缓存${t} ${n}。数据为空`)},set:async(t,n,s)=>{const a=await r.connect(e);try{s?await a.modify("cache",["namespace","key"],{namespace:t,key:n,value:s}):await a.delete("cache",{namespace:t,key:n}),await a.commit(),e.trace(`写入缓存${t} ${n}成功。数据为${s}`)}catch(r){await a.rollback(),e.trace(`写入缓存${t} ${n}失败。数据为${s}`),e.error(r)}}})}return n};class Y{constructor(e){this.req=e,this._id=e.sumor.cookie.t,this._user=null,this._permission={},this._data={},this._time=0}async update({user:e,data:t,permission:n}){e&&(this._user=e,this.req.sumor.db&&this.req.sumor.db.setUser(e)),n&&(this._permission=n),t&&(this._data=t),await this.save()}get id(){return this._id||""}set id(e){throw new Error("sumorApp.TOKEN_ID_EDIT_FORBIDDEN_DIRECTLY")}get time(){return this._time||""}set time(e){throw new Error("sumorApp.TOKEN_TIME_EDIT_FORBIDDEN_DIRECTLY")}get data(){return this._data||{}}set data(e){throw new Error("sumorApp.TOKEN_DATA_EDIT_FORBIDDEN_DIRECTLY")}get user(){return this._user||""}set user(e){throw new Error("sumorApp.USER_EDIT_FORBIDDEN_DIRECTLY")}get permission(){return this._permission}set permission(e){throw new Error("sumorApp.PERMISSION_EDIT_FORBIDDEN_DIRECTLY")}async setData(e,t){this._data[e]=t,await this.save()}async setPermission(e,t){if(e){let n={};if("string"==typeof e)n[e]=t||[];else if("array"===G(e))for(let t of e)n[t]=[];else n=e;for(let e in n)this._permission[e]=this._permission[e]||[],this._permission[e]=this._permission[e].concat(n[e]);await this.save()}}has(e,t){let n=!1;return this._permission[e]&&(t?this._permission[e].indexOf(t)>=0&&(n=!0):n=!0),n}check(e,t){if(!this.user)throw new Error("sumorApp.LOGIN_EXPIRED");if(e){let n,r=[];const s=(e,t)=>{t?r.push(`${e}-${t}`):r.push(`${e}`)};if("string"==typeof e)n=this.has(e,t),n||s(e,t);else for(let t in e){const r=e[t];"string"==typeof r?(n=this.has(r,""),n||s(r,"")):(n=this.has(r.key,r.value),n||s(r.key,r.value))}const a=r.length>0;if(r.length>0){const e=new Error("sumorApp.PERMISSION_DENIED");throw e.data={auth:r.join(",")},e}return a}}async destroy(){""!==this.id&&(await this.req.sumor.cache.set("token",this.id,void 0),delete this.req.sumor.cookie.t)}async load(){if(""!==this.id){let e=await this.req.sumor.cache.get("token",this.id);e?(e=JSON.parse(e),this._user=e.user||null,this._time=e.time||0,this._data=e.data||{},this._permission=e.permission||{}):(this._id=null,this.req.sumor.cookie.t=this._id)}}async save(){this._id||(this._id=o(),this.req.sumor.cookie.t=this._id),await this.req.sumor.cache.set("token",this._id,JSON.stringify({user:this.user,data:this.data,permission:this._permission,time:Date.now()}))}}class X{constructor(e,t){this.req=e,this.res=t,this.respond=!1,this._changed=!1,this._hasError=!1,this._code="OK",this._message="",this._data=null}set code(e){const t=this.req.sumor.text(e,this._data);e&&t?(this._code=e,this._message=t):(this._code="sumorApp.NETWORK_ERROR",this._message=this.req.sumor.text(this._code))}get code(){return this._code}set message(e){this._message=e}get message(){return this._message}set data(e){this._data=e,this._changed=!0}get data(){return this._data}set changed(e){this._changed=e}get changed(){return this._changed}error(e){this.code=e,this._hasError=!0}end(){if(void 0!==this._data)try{this.res.send(this._data)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}}send(){const e={code:this._code,message:this._message,data:this._data};if(this._hasError)try{this.res.status(500),"html"===this.req.accepts(["html","json"])?this.res.send((({title:e,code:t,desc:n,data:r})=>`<html>\n<head>\n<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">\n<style type="text/css">\nhtml{\n background: #273343;\n color: #fff;\n text-align: center;\n padding: 30px;\n}\n.title{\n opacity: .6;\n padding-bottom: 10px;\n}\n.content{\n padding-bottom: 10px;\n}\n.showDetail{\n margin-top: 20px;\n color: #03a9f4;\n cursor: pointer;\n}\n.showDetail.show{\n display: none;\n}\n.detailBox{\n position: relative;\n opacity: 0;\n}\n.detailBox.show{\n opacity: 1;\n}\npre{\n border: 1px solid rgba(255,255,255,.6);\n border-radius: 2px;\n text-align: left;\n height: 50%;\n max-width: 500px;\n margin: 0 auto;\n margin-top: 20px;\n overflow: auto;\n padding: 10px;\n}\n.detailMessage{\n font-size: 14px;\n width: fit-content;\n margin: 0 auto;\n margin-top: 5px;\n}\n</style>\n</head>\n<body>\n<h1>${e}</h1>\n<div class="title">错误原因</div>\n<div class="content">${t} ${n}</div>\n<div class="title showDetail" onclick="show()">点击查看详细错误信息</div>\n<div class="detailBox">\n <pre>${JSON.stringify(r,null,4)}</pre>\n <div class="detailMessage">请将该技术信息提供给应用管理员</div>\n</div>\n<script>\nfunction show(){\n var oDiv = document.getElementsByTagName('div')[2];\n oDiv.classList.add('show')\n var oPre = document.getElementsByTagName('div')[3];\n oPre.classList.add('show');\n}\n<\/script>\n</body>\n</html>`)({title:"服务异常,请稍后再试",...e})):this.res.send(e)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}else try{this.res.set("Content-Type","application/json;charset=utf-8"),this.res.send(e)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}}}const Q=require("ali-oss");var V=n.n(Q);const ee={resize:{mode:"m",width:"w",height:"h",longer:"l",shorter:"s"},quality:{related:"q",absolute:"Q"},circle:{radius:"r"},blur:{radius:"r",size:"s"}},te=require("path");var ne=n.n(te);const re=require("crypto");var se=n.n(re);class ae{constructor(e,t){if(this._logger=t,e)switch(e.type){case"aliyunOSS":this._instance=new class{constructor(e){this.aliyunOSS=new(V())(e)}async put(e,t){const n=await this.aliyunOSS.putStream(e,t);if(n.res.status>299){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:n.res},e}}async info(e,t){t=t||{};const n={};let r,s;try{if(r=await this.aliyunOSS.get(e,{process:"image/info"}),t.color)try{const t=await this.aliyunOSS.get(e,{process:"image/average-hue"});if(t.content){const e=JSON.parse(t.content.toString());n.color=e.RGB.replace("0x","#")}}catch(e){}}catch(e){if("NoSuchKey"===e.code)return null;s=e.message}if(!s&&r&&r.res.status>299&&(s=r.res),s){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:s},e}const a=JSON.parse(r.content.toString()),o=e=>{if(a[e])return a[e].value};return n.format=o("Format"),n.size=o("FileSize"),n.height=o("ImageHeight"),n.height&&(n.height=parseInt(n.height,10)),n.width=o("ImageWidth"),n.width&&(n.width=parseInt(n.width,10)),n.make=o("LensMake"),n.model=o("LensModel"),n}async get(e,t){let n,r,s;try{r=await this.aliyunOSS.getStream(e,(e=>{let t={};if(e.image){let n=[];for(let t in ee){const r=e.image[t];if(r){let e=[];e.push(t);for(let n in ee[t])r[n]&&e.push(`${ee[t][n]}_${r[n]}`);n.push(e.join(","))}}e.image.format&&n.push(`format,${e.image.format}`),e.image.orient&&n.push("auto-orient,1"),n.length>0&&(t.process=`image/${n.join("/")}`)}return t})(t))}catch(e){"NoSuchKey"!==e.code&&(s=e.message)}if(!s&&r&&r.res.status>299&&(s=r.res),s){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:s},e}return r&&(n=r.stream),n}async delete(e){const t=await this.aliyunOSS.delete(e);if(t.res.status>299){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:t.res},e}}async exists(e){let t=!0;try{await this.aliyunOSS.get(e)}catch(e){if("NoSuchKey"!==e.code)throw new Error("sumorStorage.STORAGE_INSTANCE_ERROR");t=!1}return t}}(e);break;case"file":this._instance=new class{constructor(e){this.config=e,this.root=ne().resolve(process.cwd(),this.config.path)}_getTargetPath(e){return ne().join(this.root,e)}async put(e,t){const n=this._getTargetPath(e);g().ensureFileSync(n),await new Promise((e=>{let r=g().createWriteStream(n,{encoding:"utf8",start:0});t.pipe(r),t.on("end",(function(){e()}))}))}async get(e){const t=this._getTargetPath(e);if(await g().exists(t))return g().createReadStream(t)}async delete(e){const t=this._getTargetPath(e);await g().remove(t)}async exists(e){const t=this._getTargetPath(e);return await g().exists(t)}}(e)}}async put(e,t){if(t=l(t),!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{const n=(e=>{let t={},n=se().createHash("md5"),r=0;return e.on("data",(e=>{r+=e.length})),e.on("data",n.update.bind(n)),e.on("end",(function(){t.length=r,t.hash=n.digest("hex")})),t})(t),r=await this._instance.put(e,t);return n.response=r,n}catch(e){throw new Error("sumorStorage.STORAGE_FILE_SAVE_FAILED")}}async get(e,t){if(t=t||{},!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{const n=await this._instance.get(e,t);return await m(n,t.type)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_READ_FAILED")}}async delete(e){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.delete(e)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_DELETE_FAILED")}}async info(e,t){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.info(e,t)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_INFO_FAILED")}}async exists(e){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.exists(e)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_INFO_FAILED")}}}const oe=require("@alicloud/sms-sdk");var ie=n.n(oe);let ce;class le{constructor(e,t){this._config=e,this._logger=t||{error:console.log,debug:console.log,trace:console.log}}async send(e,t,n,r){const{signName:s,accessKeyId:a,secretAccessKey:o}=this._config;if(this._config&&!this._config.disable){if(ce||(ce=new(ie())({accessKeyId:a,secretAccessKey:o})),86!==t)throw await new Promise((e=>{setTimeout((()=>{e()}),1e3)})),new Error("sumorSMS.MOBILE_PREFIX_NOT_SUPPORT");if(!n.match(/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/))throw new Error("sumorSMS.MOBILE_FORMAT");try{await new Promise(((t,a)=>{ce.sendSMS({PhoneNumbers:n,SignName:s,TemplateCode:e,TemplateParam:JSON.stringify(r)}).then((function(e){let{Code:n}=e;"OK"===n?t():a(n)}),(function(e){a(e.data.Code)}))}))}catch(e){const t=new Error("sumorSMS.SMS_SEND_FAILED");throw t.data={msg:e},t}}else this._logger.error(`消息发送功能不可用。需要发送消息${e}给${t} ${n},参数${JSON.stringify(r)}`)}}var ue=n(167),me=n.n(ue),pe=n(147),de=n.n(pe);const ge=require("jsrsasign"),he=18e5;class we{constructor(e,t,n){this._config=e,this._cache=t,this._name=e.name||"",this._logger=n,this._updatingToken=!1,e.pay&&(this.pay=(e=>{const t=`${process.cwd()}/${e.pay.privateKey}`,n=de().readFileSync(t,"utf8"),r=function(e,t="SHA256withRSA"){const r=e.join("\n")+"\n",s=new ge.KJUR.crypto.Signature({alg:t,prvkeypem:n});s.updateString(r);const a=s.sign();return(0,ge.hextob64)(a)},s=async t=>{let n=Math.floor(Date.now()/1e3),s=Math.random().toString(36).substr(2,15);const a=r([t.method.toUpperCase(),t.url,n,s,t.body]);let o={"Content-Type":"application/json",Accept:"application/json",Authorization:`WECHATPAY2-SHA256-RSA2048 mchid="${e.pay.mchId}",nonce_str="${s}",signature="${a}",timestamp="${n}",serial_no="${e.pay.serialNo}"`};try{return(await me()({method:t.method.toUpperCase(),url:"https://api.mch.weixin.qq.com"+t.url,data:t.body,headers:o})).data}catch(e){throw e.response}};return{sign:r,order:async function(t){t.desc=t.desc||"虚拟商品";let n={method:"POST",url:"/v3/pay/transactions/jsapi",body:JSON.stringify({appid:e.key,mchid:e.pay.mchId,description:t.desc,out_trade_no:t.id,notify_url:e.pay.notifyUrl,amount:{total:Math.round(100*t.amount),currency:"CNY"},payer:{openid:t.openId}})};return(await s(n)).prepay_id},check:async function(t){return await s({method:"GET",url:`/v3/pay/transactions/out-trade-no/${t}?mchid=${e.pay.mchId}`})},close:async function(t){let n={method:"POST",url:`/v3/pay/transactions/out-trade-no/${t}/close`,body:JSON.stringify({mchid:e.pay.mchId,out_trade_no:t})};return await s(n)}}})(e))}async call(e,t){let n;try{n=t?await me().post(e,t):await me().get(e)}catch(e){const t=new Error("WECHAT_API_FAILED");throw t.data={msg:"微信服务器连接失败:"+e.message},t}if(n.data.errcode){this._logger.error();const e=new Error("WECHAT_ERROR");throw e.data={msg:n.data.errmsg},e}return n.data}async init(e){this._app=e,this._logger.info(`微信校验文件已启动 /MP_verify_${this._config.verifyCode}.txt`),e.get(`/MP_verify_${this._config.verifyCode}.txt`,((e,t)=>{t.send(this._config.verifyCode)})),await this.getToken(),setInterval((()=>{this._logger.trace("开始检查微信服务授权凭证是否过期"),this.getToken(),this._logger.trace("检查微信服务授权凭证已完成")}),6e4)}async getToken(){const e=async()=>{let e=await this._cache.get("wechatAccessToken",this._name);return e&&(e=JSON.parse(e)),e=e||{},e.time=e.time||0,e};let t=await e();return Date.now()-t.time>he&&(await this._refreshToken(),t=await e()),(!t||!t.token||Date.now()-t.time>he)&&this._logger.error("微信服务授权凭证更新失败"),t.token}async reloadUsers(){let e,t="",n=0,r=[];const s=async()=>{const a=await this.list(t);e||(e=a.total),n+=a.count,r=r.concat(a.data.openid),n<e&&(t=a.next_openid,await s())};await s();const a=[];for(let e of r)a.push(await this.detail(e));return a}async list(e){e=e||"";const t=`https://api.weixin.qq.com/cgi-bin/user/get?access_token=${await this.getToken()}&next_openid=${e}`;return await this.call(t)}async detail(e){const t=`https://api.weixin.qq.com/cgi-bin/user/info?access_token=${await this.getToken()}&openid=${e}`;return await this.call(t)}async sendTemplateMessage(e,t,n,r){const s=await this.getToken();let a={};for(let e in r)a[e]={value:r[e]};const o=`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${s}`;try{await this.call(o,{touser:e,template_id:t,url:n,data:a}),this._logger.debug(`模版消息已发送给${e},模版${t},数据${JSON.stringify(r)}`)}catch(n){this._logger.error(`给${e}的模版消息发送失败,模版${t},数据${JSON.stringify(r)}`),this._logger.error(n)}}async updateMenu(e){const t=await this.getToken();await this.call(`https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${t}`,e)}async _refreshToken(){if(!this._updatingToken){this._updatingToken=!0,this._logger.info("正在更新微信服务授权凭证");const e=`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this._config.key}&secret=${this._config.secret}`,t=await me().get(e);if(200===t.status){const e={};t.data.access_token?(e.token=t.data.access_token,e.time=Date.now(),this._logger.info("微信服务授权凭证已更新"),this._logger.info(`授权凭证: ${e.token}`),await this._cache.set("wechatAccessToken",this._name,JSON.stringify(e))):this._logger.error(t.data)}else this._logger.error(t.data);this._updatingToken=!1}}}const fe=e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.type=e.type||"any",e.placeholder=e.placeholder||"",e.required=!0===e.required,e.length=e.length||0,e.rule=e.rule||[],e.helper=e.helper||{},"string"===e.type&&(e.trim=!1!==e.trim,e.upperCase=!0===e.upperCase,e.lowerCase=!0===e.lowerCase),e),ye={text:e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.origin=e.origin||{},e.target=e.target||{},e),rule:e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.text=e.text||"",e.expression=e.expression||"",e),type:fe,entity:(e,t,n)=>{(e=e||{}).name=e.name||"",e.desc=e.desc||"",e.property=e.property||{};for(let r in e.property){const s=e.property[r].type;s&&t.type[s]?(e.property[r]=Object.assign({},t.type[s],e.property[r]),e.property[r].type=t.type[s].type):e.property[r]=fe(e.property[r]),t.type[`${n}.${r}`]=e.property[r]}return e.join=e.join||{},e},program:(e,t)=>{(e=e||{}).name=e.name||"",e.desc=e.desc||"",e.parameters=e.parameters||{};for(let n in e.parameters){const r=e.parameters[n].type;r&&t.type[r]?(e.parameters[n]=Object.assign({},t.type[r],e.parameters[n]),e.parameters[n].type=t.type[r].type):e.parameters[n]=fe(e.parameters[n])}return e}},_e=require("glob");var $e=n.n(_e);const Ee=async({condition:e,options:t})=>(t=t||{},await new Promise((function(n){$e()(e,t,(function(e,t){for(let e in t)t[e]=ne().normalize(t[e]),t[e]=t[e].replace(/\\/g,"/");n(t)}))}))),Se=e=>{let t=e.split("/"),n=t.pop().split("."),r=n.pop(),s=n.shift(),a=null;n.length>0&&(a=n.pop());const o=[...t,s].join(".");return{path:o,route:"/api/"+o.replace(/\./g,"/"),name:s,suffix:r,type:a}},ve=async(e,t,n)=>{const r={};if(await g().exists(e)){const s=t?`**/**.${t}.json`:"**/**.json",a=await Ee({condition:s,options:{cwd:e}});for(let t of a){const n=`${e}/${t}`;r[Se(t).path]=await g().readJson(n)}if(n&&"json"!==n){const s=t?`**/**.${t}.${n}`:`**/**.${n}`,a=await Ee({condition:s,options:{cwd:e}});for(let t of a){const n=`${e}/${t}`,s=Se(t);r[s.path]=r[s.path]||{},r[s.path][s.suffix]=await g().readFile(n,"utf-8")}}}return r},Te={sumorApp:{name:"轻呈云应用文本",origin:{INTERNAL_ERROR:"程序内部错误,请稍后重试,或联系管理员",NETWORK_ERROR:"网络错误,请稍后重试,或联系管理员",PERMISSION_DENIED:"没有访问该功能权限,请联系管理员。缺少权限:${auth}",LOGIN_EXPIRED:"登陆授权失效,请重新登陆",PERMISSION_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改permission,请使用setPermission",LOGIN_STATUS_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改登录状态",USER_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改user,请使用setUser",TOKEN_ID_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌ID,请使用setID",TOKEN_TIME_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌时间",TOKEN_DATA_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌数据",LACK_USER_ID:"缺少用户ID",AUTH_ERROR:"授权失败,请稍后重试",AUTH_ERROR_COOKIE_MISSING:"cookie丢失",API_NOT_FOUND:"接口未找到",INVALID_PARAMETER:"无效数据:${msg}",RULE_LOGIC_NOT_FUNCTION:"规则逻辑不是有效函数方法",SUFFIX_REQUIRED:"转换为对象缺少必要的后缀名",PATH_ARROGATION:"路径越级",NOT_SUPPORT_ABSOLUTE_PATH:"不支持绝对路径",REQUIRED:"必填项",LENGTH_OUT_OF_LIMIT:"长度必须小于${length}",WECHAT_DISABLED:"微信未启用,请联系管理员"},target:{en:{INTERNAL_ERROR:"Internal program error, please try again later, or contact administrator",NETWORK_ERROR:"Network error. Please try again later or contact the administrator",PERMISSION_DENIED:"You do not have permission ${auth}, please contact administrator",LOGIN_EXPIRED:"Login expired, please login",INVALID_PARAMETER:"Invalid data: ${msg}",RULE_LOGIC_NOT_FUNCTION:"Rule logic isn't valid function",SUFFIX_REQUIRED:"Suffix required for object path",PATH_ARROGATION:"Path arrogation",NOT_SUPPORT_ABSOLUTE_PATH:"Not support absolute path",REQUIRED:"Required",LENGTH_OUT_OF_LIMIT:"The length must be less than ${length}"}}},sumorSMS:{origin:{MOBILE_FORMAT:"手机号格式错误",MOBILE_PREFIX_NOT_SUPPORT:"该国家地区暂未开通服务",SMS_SEND_FAILED:"消息发送失败:${msg}"}},sumorStorage:{name:"轻呈云存储文本",origin:{STORAGE_INSTANCE_ERROR:"存储系统交互异常:${msg}",STORAGE_FILE_SAVE_FAILED:"文件写入失败",STORAGE_NOT_CONNECTED:"未配置存储服务器连接",STORAGE_FILE_READ_FAILED:"文件读取失败",STORAGE_FILE_DELETE_FAILED:"文件删除失败",STORAGE_FILE_INFO_FAILED:"文件获取信息失败"}},sumorDemo:{origin:{DEMO_TEXT_ZH:"演示文本:中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_ZHCN:"演示文本:中国大陆简体中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_ZHHK:"演示文本:中国香港繁体中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_EN:"演示文本:英文,当前语言环境不匹配,已回归原始文本"},target:{en:{DEMO_TEXT_EN:"Demo text for english"},zh:{DEMO_TEXT_ZH:"演示文本:中文"},"zh-CN":{DEMO_TEXT_ZHCN:"演示文本:中国大陆简体中文"},"zh-HK":{DEMO_TEXT_ZHHK:"演示文本:中國香港繁體中文"}}}},xe={"sumorApp.term":{name:"查询条件",required:!1},"sumorApp.skip":{name:"跳过条数",type:"number",default:0,required:!1},"sumorApp.top":{name:"条数",type:"number",default:100,required:!1},"sumorApp.sort":{name:"排序规则",type:"string",required:!1}},be={"sumor.language":"sq=阿尔巴尼亚语|Shqip\nsq-AL=阿尔巴尼亚语(阿尔巴尼亚)|Shqiptar (Shqipëri)\ngsw=阿尔萨斯语\ngsw-FR=阿尔萨斯语(法国)\nar=阿拉伯语|العربية\nar-DZ=阿拉伯语(阿尔及利亚)|العربية (الجزائر)\nar-AE=阿拉伯语(阿联酋)|العربية (الإمارات العربية المتحدة)\nar-OM=阿拉伯语(阿曼)|العربية (سلطنة عمان)\nar-EG=阿拉伯语(埃及)|العربية (مصر)\nar-BH=阿拉伯语(巴林)|العربية (البحرين)\nar-QA=阿拉伯语(卡塔尔)|العربية (قطر)\nar-KW=阿拉伯语(科威特)|العربية (الكويت)\nar-LB=阿拉伯语(黎巴嫩)|العربية (لبنان)\nar-LY=阿拉伯语(利比亚)|العربية (ليبيا)\nar-MA=阿拉伯语(摩洛哥)|العربية (المغرب)\nar-SA=阿拉伯语(沙特阿拉伯)|العربية (المملكة العربية السعودية)\nar-TN=阿拉伯语(突尼斯)|العربية (تونس)\nar-SY=阿拉伯语(叙利亚)|العربية (سوريا)\nar-YE=阿拉伯语(也门)|العربية (اليمن)\nar-IQ=阿拉伯语(伊拉克)|العربية (العراق)\nar-JO=阿拉伯语(约旦)|العربية (الأردن)\nam=阿姆哈拉语|አማርኛ\nam-ET=阿姆哈拉语(埃塞俄比亚)|አማርኛ (ኢትዮጵያ)\nas=阿萨姆语|অসমীয়া\nas-IN=阿萨姆语(印度)|অসম (ভাৰত)\naz=阿塞拜疆语|Azərbaycan\naz-Latn=阿塞拜疆语(拉丁语)|Azərbaycan dili (Latın dili)\naz-Latn-AZ=阿塞拜疆语(拉丁语,阿塞拜疆)|Azerbaijani (Latınca, Azerbaijani)\naz-Cyrl=阿塞拜疆语(西里尔文)|Azerbaijani (şirniyyat)\naz-Cyrl-AZ=阿塞拜疆语(西里尔文,阿塞拜疆)|Azerbaijani (Şirniyyat, Azerbaijani)\nkn=埃纳德语\nkn-IN=埃纳德语(印度) \nga=爱尔兰语 \nga-IE=爱尔兰语(爱尔兰) \net=爱沙尼亚语 \net-EE=爱沙尼亚语(爱沙尼亚) \noc=奥克西唐语 \noc-FR=奥克西唐语(法国) \nor=奥里雅语 \nor-IN=奥里雅语(印度) \nba=巴什基尔语 \nba-RU=巴什基尔语(俄罗斯) \neu=巴斯克语 \neu-ES=巴斯克语(巴斯克) \nnso=巴索托语 \nnso-ZA=巴索托语(南非) \nbe=白俄罗斯语 \nbe-BY=白俄罗斯语(白俄罗斯) \nbg=保加利亚语 \nbg-BG=保加利亚语(保加利亚) \nse=北萨米语 \nse-FI=北萨米语(芬兰) \nse-NO=北萨米语(挪威) \nse-SE=北萨米语(瑞典) \nis=冰岛语 \nis-IS=冰岛语(冰岛) \npl=波兰语 \npl-PL=波兰语(波兰) \nbs=波斯尼亚语 \nbs-Latn=波斯尼亚语(拉丁语) \nbs-L=波斯尼亚语(拉丁语,波斯尼亚和黑塞哥维那) \nbs-Cyrl=波斯尼亚语(西里尔文) \nfa=波斯语 \nfa-IR=波斯语 \n布里多尼语\nbr-FR=布里多尼语(法国) \nbo=藏语 \nbo-CN=藏语(中国) \nko=朝鲜语 \nko-KR=朝鲜语(韩国) \ntn=茨瓦纳语 \ntn-ZA=茨瓦纳语(南非) \nprs=达里语 \nprs-AF=达里语(阿富汗) \ntt=鞑靼语 \ntt-RU=鞑靼语(俄罗斯) \nda=丹麦语 \nda-DK=丹麦语(丹麦) \nde=德语 \nde-AT=德语(奥地利) \nde-DE=德语(德国) \nde-LI=德语(列支敦士登) \nde-LU=德语(卢森堡) \nde-CH=德语(瑞士) \ndv=迪维希语 \ndv-MV=迪维希语(马尔代夫) \nru=俄语 \nru-RU=俄语(俄罗斯) \nfo=法罗语 \nfo-FO=法罗语(法罗群岛) \nfr=法语 \nfr-BE=法语(比利时) \nfr-FR=法语(法国) \nfr-CA=法语(加拿大) \nfr-LU=法语(卢森堡) \nfr-MC=法语(摩纳哥) \nfr-CH=法语(瑞士) \nsa=梵语 \nsa-IN=梵语(印度) \nfil=菲律宾语 \nfil-PH=菲律宾语(菲律宾) \nfi=芬兰语 \nfi-FI=芬兰语(芬兰) \nfy=弗里西亚语 \nfy-NL=弗里西亚语(荷兰) \nkm=高棉语 \nkm-KH=高棉语(柬埔寨) \nkl=格陵兰语 \nkl-GL=格陵兰语(格陵兰) \nka=格鲁吉亚语 \nka-GE=格鲁吉亚语(格鲁吉亚) \ngu=古吉拉特语 \ngu-IN=古吉拉特语(印度) \nkk=哈萨克语 \nkk-KZ=哈萨克语(哈萨克斯坦) \nha=豪撒语 \nha-Latn=豪撒语(拉丁语) \nha-Latn-NG=豪撒语(拉丁语,尼日利亚) \nnl=荷兰语 \nnl-BE=荷兰语(比利时) \nnl-NL=荷兰语(荷兰) \nqut=基切语 \nqut-GT=基切语(危地马拉) \nky=吉尔吉斯语 \nky-KG=吉尔吉斯语(吉尔吉斯斯坦) \ngl=加利西亚语 \ngl-ES=加利西亚语(加利西亚语) \nca=加泰罗尼亚语 \nca-ES=加泰罗尼亚语(加泰罗尼亚) \ncs=捷克语 \ncs-CZ=捷克语(捷克共和国) \nco=科西嘉语 \nco-FR=科西嘉语(法国) \n克罗地亚语\nhr-HR=克罗地亚语(克罗地亚) \nhr-B=克罗地亚语(拉丁语,波斯尼亚和黑塞哥维那) \nquz=克丘亚语 \nquz-BO=克丘亚语(玻利维亚) \nquz-EC=克丘亚语(厄瓜多尔) \nquz-PE=克丘亚语(秘鲁) \nkok=孔卡尼语 \nkok-IN=孔卡尼语(印度) \nlv=拉脱维亚语 \nlv-LV=拉脱维亚语(拉脱维亚) \nlo=老挝语 \nlo-LA=老挝语(老挝人民民主共和国) \nlt=立陶宛语 \nlt-LT=立陶宛语(立陶宛) \nlb=卢森堡语 \nlb-LU=卢森堡语(卢森堡) \nrw=卢旺达语 \nrw-RW=卢旺达语(卢旺达) \nro=罗马尼亚语 \nro-RO=罗马尼亚语(罗马尼亚) \nrm=罗曼什语 \nrm-CH=罗曼什语(瑞士) \nsmj=律勒萨米语 \nsmj-NO=律勒萨米语(挪威) \nsmj-SE=律勒萨米语(瑞典) \nmt=马耳他语 \nmt-MT=马耳他语(马耳他) \nmr=马拉地语 \nmr-IN=马拉地语(印度) \nml=马拉雅拉姆语 \nml-IN=马拉雅拉姆语(印度) \nms=马来语 \nms-MY=马来语(马来西亚) \nms-BN=马来语(文莱达鲁萨兰国) \narn=马普丹冈语 \narn-CL=马普丹冈语(智利) \nmk=马其顿语\nmk-MK=马其顿语(前南斯拉夫马其顿共和国) \nmi=毛利语 \nmi-NZ=毛利语(新西兰) \nmn=蒙古语 \nmn-Mong=蒙古语(传统蒙古语) \nmn-Mong-CN=蒙古语(传统蒙古语,中国) \nmn-Cyrl=蒙古语(西里尔文) \nmn-MN=蒙古语(西里尔文,蒙古) \nbn=孟加拉语 \nbn-BD=孟加拉语(孟加拉国) \nbn-IN=孟加拉语(印度) \nmoh=莫霍克语 \nmoh-CA=莫霍克语(莫霍克) \naf=南非荷兰语 \naf-ZA=南非荷兰语(南非) \nsma=南萨米语 \nsma-NO=南萨米语(挪威) \nsma-SE=南萨米语(瑞典) \nne=尼泊尔语 \nne-NP=尼泊尔语(尼泊尔) \nnn-NO=尼诺斯克挪威语(挪威) \nno=挪威语 \nnn=尼诺斯克语\npa=旁遮普语 \npa-IN=旁遮普语(印度) \npt=葡萄牙语 \npt-BR=葡萄牙语(巴西) \npt-PT=葡萄牙语(葡萄牙) \nps=普什图语 \nps-AF=普什图语(阿富汗) \nja=日语 \nja-JP=日语(日本) \nsv=瑞典语 \nsv-FI=瑞典语(芬兰) \nsv-SE=瑞典语(瑞典) \nsr=塞尔维亚语 \nsr-Latn=塞尔维亚语(拉丁语) \nsr-Latn-ME=塞尔维亚语(拉丁语,黑山共和国) \nsr-Latn-RS=塞尔维亚语(拉丁语,塞尔维亚共和国) \nsr-Cyrl=塞尔维亚语(西里尔文) \nsr-Cyrl-ME=塞尔维亚语(西里尔文,黑山共和国) \nsr-Cyrl-RS=塞尔维亚语(西里尔文,塞尔维亚共和国) \nsi=僧伽罗语 \nsi-LK=僧伽罗语(斯里兰卡) \nhsb=上索布语 \nhsb-DE=上索布语(德国) \nnb=书面挪威语 \nnb-NO=书面挪威语(挪威) \nsms=斯科特萨米语 \nsms-FI=斯科特萨米语(芬兰) \nsk=斯洛伐克语 \nsk-SK=斯洛伐克语(斯洛伐克) \nsl=斯洛文尼亚语 \nsl-SI=斯洛文尼亚语(斯洛文尼亚) \nsw=斯瓦希里语 \nsw-KE=斯瓦希里语(肯尼亚) \ngd=苏格兰盖立语 \ngd-GB=苏格兰盖立语(英国) \nxh=索萨语 \nxh-ZA=索萨语(南非) \ntg=塔吉克语 \ntg-Cyrl=塔吉克语(西里尔文) \ntg-Cyrl-TJ=塔吉克语(西里尔文,塔吉克斯坦) \ntzm=塔马塞特语 \ntzm-Latn=塔马塞特语(拉丁语) \ntzm-Latn-DZ=塔马塞特语(拉丁语,阿尔及利亚) \nth=泰国语 \nte=泰卢固语 \nte-IN=泰卢固语(印度) \nta=泰米尔语 \nta-IN=泰米尔语(印度) \nth-TH=泰语(泰国) \ntr=土耳其语 \ntr-TR=土耳其语(土耳其) \ntk=土库曼语 \ntk-TM=土库曼语(土库曼斯坦) \ncy=威尔士语 \ncy-GB=威尔士语(英国) \nug=维吾尔语 \nug-CN=维吾尔语(中国) \nwo=沃洛夫语 \nwo-SN=沃洛夫语(塞内加尔) \nur=乌尔都语 \nur-PK=乌尔都语(巴基斯坦伊斯兰共和国) \nuk=乌克兰语 \nuk-UA=乌克兰语(乌克兰) \nuz=乌兹别克语 \nuz-Latn=乌兹别克语(拉丁语) \nuz-Latn-UZ=乌兹别克语(拉丁语,乌兹别克斯坦) \nuz-Cyrl=乌兹别克语(西里尔文) \nuz-Cyrl-UZ=乌兹别克语(西里尔文,乌兹别克斯坦) \nes=西班牙语 \nes-AR=西班牙语(阿根廷) \nes-PY=西班牙语(巴拉圭) \nes-PA=西班牙语(巴拿马) \nes-PR=西班牙语(波多黎各) \nes-BO=西班牙语(玻利维亚) \nes-DO=西班牙语(多米尼加共和国) \nes-EC=西班牙语(厄瓜多尔) \nes-CO=西班牙语(哥伦比亚) \nes-CR=西班牙语(哥斯达黎加) \nes-HN=西班牙语(洪都拉斯) \nes-US=西班牙语(美国) \nes-PE=西班牙语(秘鲁) \nes-MX=西班牙语(墨西哥) \nes-NI=西班牙语(尼加拉瓜) \nes-SV=西班牙语(萨尔瓦多) \nes-GT=西班牙语(危地马拉) \nes-VE=西班牙语(委内瑞拉玻利瓦尔共和国) \nes-UY=西班牙语(乌拉圭) \nes-ES=西班牙语(西班牙,国际排序) \nes-CL=西班牙语(智利) \nhe=希伯来语 \nhe-IL=希伯来语(以色列) \nel=希腊语 \nel-GR=希腊语(希腊) \ndsb=下索布语 \ndsb-DE=下索布语(德国) \nhu=匈牙利语 \nhu-HU=匈牙利语(匈牙利) \nsyr=叙利亚语 \nsyr-SY=叙利亚语(叙利亚) \nsah=雅库特语 \nsah-RU=雅库特语(俄罗斯) \nhy=亚美尼亚语 \nhy-AM=亚美尼亚语(亚美尼亚) \nig=伊博语 \nig-NG=伊博语(尼日利亚) \nsmn=伊纳里萨米语 \nsmn-FI=伊纳里萨米语(芬兰) \nii=彝语 \nii-CN=彝语(中国) \nit=意大利语 \nit-CH=意大利语(瑞士) \nit-IT=意大利语(意大利) \niu=因纽特语 \niu-Latn=因纽特语(拉丁语) \niu-Latn-CA=因纽特语(拉丁语,加拿大) \niu-Cans=因纽特语(音节) \niu-Cans-CA=因纽特语(音节,加拿大) \nhi=印地语 \nhi-IN=印地语(印度)\nid=印度尼西亚语\nid-ID=印度尼西亚语(印度尼西亚)\nen=英语\nen-IE=英语(爱尔兰)\nen-AU=英语(澳大利亚)\nen-BZ=英语(伯利兹)\nen-PH=英语(菲律宾共和国)\nen-029=英语(加勒比海)\nen-CA=英语(加拿大)\nen-ZW=英语(津巴布韦)\nen-MY=英语(马来西亚)\nen-US=英语(美国)\nen-ZA=英语(南非)\nen-TT=英语(特立尼达和多巴哥)\nen-SG=英语(新加坡)\nen-NZ=英语(新西兰)\nen-JM=英语(牙买加)\nen-IN=英语(印度)\nen-GB=英语(英国)\nyo=约鲁巴语\nyo-NG=约鲁巴语(尼日利亚)\nvi=越南语\nvi-VN=越南语(越南)\nzh=中文\nzh-Hant=中文(繁体)\nzh-MO=中文(繁体,澳门特别行政区)\nzh-TW=中文(繁体,台湾)\nzh-HK=中文(繁体,香港特别行政区)\nzh-CN=中文(简体)\nzh-SG=中文(简体,新加坡)\nzu=祖鲁语\nzu-ZA=祖鲁语(南非)"},Oe=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,cache:c,logger:l,response:u}=e;if(!a.wechat)throw"sumorApp.WECHAT_DISABLED";if(s.data.wechatOpenId)u.respond=!0,n.redirect(o+r.source);else{u.respond=!0;const e={appid:a.wechat.key,redirect_uri:`${o}/wx/authCallback`,response_type:"code",scope:"snsapi_base"};r.source&&(e.redirect_uri=e.redirect_uri+`?target=${encodeURIComponent(r.source)}`);const t=`https://open.weixin.qq.com/connect/oauth2/authorize?${(e=>{let t=[];for(let n in e)t.push([n,e[n]].join("="));return t.join("&")})(e)}#wechat_redirect`;l.trace("获取用户微信授权",t),n.redirect(t)}},Ne=n(167),Ie=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,cache:c,saveCookie:l,logger:u,response:m}=e;if(!a.wechat)throw"sumorApp.WECHAT_DISABLED";{m.respond=!0;const e=`https://api.weixin.qq.com/sns/oauth2/access_token?${(e=>{let t=[];for(let n in e)t.push([n,e[n]].join("="));return t.join("&")})({appid:a.wechat.key,secret:a.wechat.secret,code:r.code,grant_type:"authorization_code"})}`;u.trace("获取用户微信令牌",e);const t=(await Ne.get(e)).data.openid;await s.setData("wechatOpenId",t),l(),n.redirect(o+r.target)}},ke=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,logger:c,response:l,tools:u,wechat:m}=e;if(a.wechat){l.respond=!0;const e=r.id,t={appId:a.wechat.key,timeStamp:Math.round(Date.now()/1e3),nonceStr:u.uuid(),package:`prepay_id=${e}`,signType:"RSA"};t.paySign=m.pay.sign([t.appId,t.timeStamp,t.nonceStr,t.package]),n.end(`\n<html>\n<body>\n<h1 id="message">正在启动微信支付,请稍后。如遇到问题,请稍后重试或联系客服。</h1>\n<script>\nfunction onBridgeReady() {\n WeixinJSBridge.invoke('getBrandWCPayRequest', ${JSON.stringify(t)},\n function(res) {\n if (res.err_msg == "get_brand_wcpay_request:ok") {\n // 使用以上方式判断前端返回,微信团队郑重提示:\n //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。\n \n var divElem = document.getElementById('message'); // 获取指定ID的div元素\n divElem.innerHTML = '支付完成'; // 修改div元素中的内容\n setTimeout(function (){\n var target = '${a.wechat.pay.callback||""}';\n if(target&&target!==""){\n window.location.href = target;\n }else{\n var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n if(isChrome) {\n window.location.href = 'about:blank';\n window.close();\n } else {\n window.close();\n }\n }\n },1000);\n }\n });\n}\nif (typeof WeixinJSBridge == "undefined") {\n if (document.addEventListener) {\n document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);\n } else if (document.attachEvent) {\n document.attachEvent('WeixinJSBridgeReady', onBridgeReady);\n document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);\n }\n} else {\n onBridgeReady();\n}\n<\/script>\n</body>\n</html>`)}},Re=async e=>{e.disable("x-powered-by"),e.sumor={app:e,root:process.cwd(),tools:p},await(async e=>{const t=(e=>{const t={monitor:{name:"服务健康状态监控",program:async(e,t,n)=>t.sumor.monitor},text:{name:"当前语言环境文本数据",program:async(e,t,n)=>t.sumor.text()},token:{name:"当前授权登录令牌",program:(e,t,n,r)=>{const s=t.sumor.token;if(s.id){const e=s.data?s.data.nickname:"";return{id:s.id,user:s.user,nickname:e,time:s.time,permission:s.permission}}return{}}},logout:{name:"退出登录",program:async(e,t,n,r)=>{const s=t.sumor.token;s.user&&await s.destroy()}},range:{name:"数据输入范围列表",parameters:{name:{name:"数据名称",desc:"帮助数据的名称",required:!0,type:"string"}},program:async(e,t,n)=>{const r=t.sumor.data.name;return t.sumor.range(r)}},meta:{name:"接口信息",program:async(t,n,r)=>({name:e.sumor.name,instance:e.sumor.instance,api:e.sumorRuntime.exposeApis,text:n.sumor.text()})}};let n={};for(let e in t)n[`sumor.${e}`]=t[e];return n["wx.auth"]={name:"微信授权",parameters:{source:{name:"来源地址",required:!0,type:"string"}},program:Oe},n["wx.authCallback"]={name:"微信授权完成回调",parameters:{code:{name:"微信授权码",required:!0,type:"string"},target:{name:"授权完成跳转地址",required:!0,type:"string"}},program:Ie},n["wx.pay"]={name:"微信支付",program:ke},n})(e),r={};for(let e in t)r[e]={name:t[e].name,parameters:t[e].parameters};const s=["text","rule","type","entity","view","api","event"];let a={range:be,text:Te,type:xe,api:r};for(let t of s){let n=t;a[t]=a[t]||{},"api"!==t&&"event"!==t||(n="program");let r=await ve(`${e.sumor.root}/${t}`,n);if("api"===t){let e={};for(let t in r)e[`api.${t}`]=r[t];r=e}if(a[t]=Object.assign(a[t],r),ye[n])for(let e in a[t])a[t][e]=ye[n](a[t][e],a,e)}await g().ensureDir(`${process.cwd()}/tmp`),await g().writeFile(`${process.cwd()}/tmp/meta.json`,JSON.stringify(a,null,4));for(let e in t)a.api[e]=t[e];const o=await ve(`${e.sumor.root}/view`,"view","sql");for(let e in o)a.view[e]=a.api[e]||ye.program({}),a.view[e]=Object.assign(a.view[e],o[e]);const i=`${e.sumor.root}/api`;if(await g().exists(i)){const e=await Ee({condition:"**/**.js",options:{cwd:i}});for(let t of e){const e=`api.${Se(t).path}`,r=`${i}/${t}`;a.api[e]=a.api[e]||{},a.api[e].program=n.g.globalRequire(r)}}const c=`${e.sumor.root}/event`;if(await g().exists(c)){const e=await Ee({condition:"**/**.js",options:{cwd:c}});for(let t of e){const e=Se(t).path,r=`${c}/${t}`;a.event[e]=a.event[e]||{},a.event[e].program=async t=>{t.logger.debug(`正在执行事件${e}`);let s,a=Object.assign({},t);if(t.db||(s=await t.connectDB(),a=Object.assign(a,{db:s})),n.g.globalRequire)try{await n.g.globalRequire(r)(a||t),s&&await s.commit(),t.logger.debug(`事件${e}完成`)}catch(n){s&&await s.rollback(),t.logger.error(`事件${e}执行失败,${n.message}`),t.logger.trace(n)}else t.logger.error(`事件${e}执行失败,该程序不存在`)}}}e.sumor.meta=a})(e),e.sumorRuntime={},e.use(((e,t,n)=>{e.sumor={cors:!1,ip:e.headers["x-forwarded-for"]||"0.0.0.0",tools:p},n()})),await(async e=>{const t=`${e.sumor.root}/config.json`;let n={};if(await g().exists(t))try{n=await g().readJson(t)}catch(e){}const r=await(async e=>{if(await g().exists(e)){const t={key:await g().readFile(`${e}/domain.key`,"utf-8"),cert:await g().readFile(`${e}/domain.cer`,"utf-8")};return await g().exists(`${e}/ca.cer`)&&(t.ca=await g().readFile(`${e}/ca.cer`,"utf-8")),t}})(`${e.sumor.root}/ssl`);let s=n.protocol||"https";"https"!==s||r||(s="http");const a=n.name||"轻呈云应用",o=n.domain||"localhost",i=parseInt(n.port||("http"===s?80:443),10),c="http"===s&&80===i||"https"===s&&443===i?"":`:${i}`,l=n.origin||`${s}://${o}${c}`,u=n.logLevel||"info",m=n.language||"zh-CN";e.sumor={...e.sumor,name:a,ssl:r,protocol:s,domain:o,port:i,origin:l,logLevel:u,language:m,config:n},e.use(((e,t,r)=>{e.sumor={...e.sumor,protocol:s,domain:o,port:i,origin:l,config:JSON.parse(JSON.stringify(n))},r()}))})(e),await(async e=>{const t=`${e.sumor.root}/instance.json`;let n={};if(await g().exists(t))try{n=await g().readJson(t)}catch(e){}e.sumor.instance=JSON.parse(JSON.stringify(n)),e.use(((e,t,r)=>{if(e.sumor.instance=JSON.parse(JSON.stringify(n)),e.sumor.instance){const{server:n,port:r,upTime:s}=e.sumor.instance;t.set("sumor-instance",`${n}_${r}_${s}`)}r()}))})(e),await(async e=>{e.use(((e,t,n)=>{e.sumor.response=new X(e,t),n()}))})(e),await(e=>{e.use(((t,n,r)=>{const s=(t.get("accept-language")||e.sumor.language).split(","),a=s[0];let o=[];for(let e in s)o.push(s[e].split(";")[0]);t.sumor.language=a,t.sumor.languages=o,r()}))})(e),await(async e=>{const t={};for(let n in e.sumor.meta.text){t[n]=t[n]||{},t[n][""]=e.sumor.meta.text[n].origin||{};for(let r in e.sumor.meta.text[n].target)t[n][r]=e.sumor.meta.text[n].target[r]||{}}e.sumor.text=h(t,e.sumor.language),e.use(((e,n,r)=>{e.sumor.text=h(t,e.sumor.language),r()}))})(e),await(async e=>{e.sumor.range=t=>t?e.sumor.meta.range[t]:e.sumor.meta.range,e.use(((t,n,r)=>{t.sumor.range=e.sumor.range,r()}))})(e),await(e=>{e.use(((e,t,n)=>{e.sumor.timezone=e.get("sumor-timezone"),n()}))})(e),await(e=>{E.setProduction(e.sumor.config.production),E.setLevel(e.sumor.config.logLevel),e.sumor.logger=new E("APP"),e.sumor.logger.info(`日志记录级别:${e.sumor.config.logLevel.toUpperCase()}`),e.sumor.getLogger=e=>new E(e),e.use(((e,t,n)=>{const r=++S,s=e=>new E(e,r);e.sumor.getLogger=s,e.sumor.logger=s("PROGRAM");const a=e.sumor.getLogger("HTTP"),o=e.headers["user-agent"]||"unknown agent";a.trace(`${e.method} ${e.originalUrl} IP/${e.sumor.ip} ${o}`),n()}))})(e),await(async e=>{k(),setInterval((()=>{k()}),6e4),e.use(((e,t,n)=>{e.sumor.monitor=JSON.parse(JSON.stringify(N)),n()}))})(e),await(async e=>{const t=`${e.sumor.root}/tmp/uploads`;await g().ensureDir(t);const n=L()({dest:"tmp/uploads/"});e.uploader=e=>{let t;if(e){let r=[];for(let t in e)"file"===e[t].type&&r.push({name:t});r.length>0&&(t=n.fields(r))}return t},e.use(D().urlencoded({extended:!1})),e.use(D().json()),e.use(D().text())})(e),await(e=>{e.use(q()()),e.use(((e,t,n)=>{e.sumor.cookie=JSON.parse(JSON.stringify(e.cookies)),e.sumor.saveCookie=()=>{for(let n in e.cookies)e.sumor.cookie[n]||t.clearCookie(n);for(let n in e.sumor.cookie)e.sumor.cookie[n]!==e.cookies[n]&&t.cookie(n,e.sumor.cookie[n],{maxAge:31536e6,httpOnly:!0})},n()}))})(e),await(async e=>{const t=e.sumor.config.cache||{},n=e.sumor.getLogger("CACHE"),r=await Z(t,n);e.sumor.cache=r(n),e.use((async(e,t,n)=>{const s=e.sumor.getLogger("CACHE");e.sumor.cache=r(s),n()}))})(e),await(async e=>{e.use((async(e,t,n)=>{e.sumor.token=new Y(e),await e.sumor.token.load(),n()}))})(e),await(async e=>{const t=e.sumor.config.database,n=e.sumor.getLogger("DATABASE");await W({config:t,logger:n,entity:e.sumor.meta.entity,view:e.sumor.meta.view});const r=await K({config:t,logger:n});e.sumor.connectDB=async()=>await r.connect(n),e.use((async(e,t,n)=>{const s=e.sumor.getLogger("DATABASE");e.sumor.connectDB=async()=>await r.connect(s),e.sumor.db=await e.sumor.connectDB(),e.sumor.token.user&&e.sumor.db.setUser(e.sumor.token.user),n()}))})(e),await(async e=>{const t=e.sumor.getLogger("STORAGE");e.sumor.storage=new ae(e.sumor.config.storage,t),e.use(((t,n,r)=>{const s=t.sumor.getLogger("STORAGE");t.sumor.storage=new ae(e.sumor.config.storage,s),r()}))})(e),await(async e=>{if(e.sumor.config.sms){const t=e.sumor.getLogger("SMS");e.sumor.sms=new le(e.sumor.config.sms,t)}e.use(((t,n,r)=>{if(e.sumor.config.sms){const n=t.sumor.getLogger("SMS");t.sumor.sms=new le(e.sumor.config.sms,n)}r()}))})(e),await(async e=>{if(e.sumor.config.wechat){const t=e.sumor.getLogger("WECHAT");let n;t.debug("微信服务器正在启动"),n=e.sumor.config.wechat.cache?(await Z(e.sumor.config.wechat.cache,t))(t):e.sumor.cache,t.trace(`微信服务器配置信息 ${JSON.stringify(e.sumor.config.wechat)}`),e.sumor.wechat=new we(e.sumor.config.wechat,n,t),await e.sumor.wechat.init(e),t.debug("微信服务器已启动"),e.use(((t,n,r)=>{const s=t.sumor.getLogger("WECHAT");t.sumor.wechat=new we(e.sumor.config.wechat,s),r()}))}})(e)},De=(e,t,n)=>{const r="/"+e.replace(/\./g,"/"),s=`${t.sumor.root}/tmp/uploads`;let a=t.uploader(t.sumor.meta.api[e].parameters);return a?t.all(r,a,((e,t,n)=>{const r={};if(e.files)for(let t in e.files){const n=[];for(let r in e.files[t])n.push({name:e.files[t][r].originalname,size:e.files[t][r].size,mime:e.files[t][r].mimetype,encoding:e.files[t][r].encoding,path:`${s}/${e.files[t][r].filename}`});r[t]=n}e.sumor.data=Object.assign({},e.query,e.body,r),n()}),n):t.all(r,((e,t,n)=>{e.sumor.data=Object.assign({},e.query,e.body),n()}),n),!!a},Ae=(e,t)=>{for(let n in t.parameters){const r=t.parameters[n];switch(void 0!==r.default&&("string"===r.type?null!==e[n]&&void 0!==e[n]&&""!==e[n]||(e[n]=r.default):null!==e[n]&&void 0!==e[n]||(e[n]=r.default)),r.type){case"string":null!==e[n]&&void 0!==e[n]&&"string"!=typeof e[n]&&(e[n]=e[n].toString());break;case"number":"number"!=typeof e[n]&&null!==e[n]&&void 0!==e[n]&&("string"==typeof e[n]?(e[n]=parseFloat(e[n]),isNaN(e[n])&&(e[n]=null)):delete e[n])}if(e[n]&&(r.trim&&(e[n]=e[n].trim()),r.upperCase&&(e[n]=e[n].toUpperCase()),r.lowerCase&&(e[n]=e[n].toLowerCase())),!0===r.required&&(void 0===e[n]||null===e[n]||""===e[n]))throw new Error("sumorApp.REQUIRED");if(r.length&&e[n]&&e[n].length>r.length){const e=new Error("sumorApp.LENGTH_OUT_OF_LIMIT");throw e.data={length:r.length},e}for(let t of r.rule)if(!new RegExp(t.expression).test(e[n]))throw new Error(t.text)}return e},Le=require("compression");var Ce=n.n(Le);const qe=require("zlib");var Fe=n.n(qe);const Pe=require("serve-static");var je=n.n(Pe),ze=n(525),Me=n.n(ze);const Be=require("http");var He=n.n(Be);const Ue=require("spdy");var Ge=n.n(Ue);const Je=e=>{const t=[];return e.on("connection",(function(e){t.push(e),e.once("close",(function(){t.splice(t.indexOf(e),1)}))})),async()=>await new Promise((n=>{t.forEach((function(e){e.destroy()})),e.close((function(){n()}))}))},Ke=async()=>{const e=t()();await Re(e),e.sumor.logger.trace("前置中间件加载完成"),e.sumor.meta.event.setup&&e.sumor.meta.event.setup.program(e.sumor),e.sumor.meta.event.prepare&&e.sumor.meta.event.prepare.program(e.sumor),await(async e=>{e.sumorRuntime.exposeApis={};const t=Object.keys(e.sumor.meta.api);t.sort(((e,t)=>e>t?1:-1));for(let n of t){const t="/"+n.replace(/\./g,"/"),r=async function(t,r,s){t.sumor.meta=e.sumor.meta,t.sumor.cors=!0,t.sumor.response.changed=!0,e.sumor.meta.event.context&&e.sumor.meta.event.context.program(t.sumor,t,r);try{const s=e.sumor.meta.api[n];t.sumor.data=Ae(t.sumor.data,s);const a=await s.program(t.sumor,t,r);t.sumor.response.data=a||t.sumor.response.data,await t.sumor.db.commit()}catch(n){try{await t.sumor.db.rollback()}catch(e){}t.sumor.response.error(n.message);let r="";n instanceof Error&&(r=e.sumor.text(n.message)),t.sumor.logger.debug(`外部请求出错:${n.message} ${r}`),t.sumor.logger.trace(n)}s()},s=De(n,e,r);e.sumorRuntime.exposeApis[t]={name:e.sumor.meta.api[n].name||"",desc:e.sumor.meta.api[n].desc||"",parameters:e.sumor.meta.api[n].parameters||{}},e.sumor.logger.info(`接口已就绪:${t}${s?" (允许文件上传)":""}`)}e.sumor.logger.info("所有接口已就绪")})(e),e.sumor.logger.trace("处理程序加载完成"),await(async e=>{await(e=>{e.use(((e,t,n)=>{e.sumor.cors&&(t.header("Access-Control-Allow-Origin","*"),t.header("Access-Control-Allow-Headers","X-Requested-With"),t.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS")),n()}))})(e),await(e=>{e.use((async(t,n,r)=>{if(t.files){const n=`${e.sumor.root}/tmp/uploads`;for(let e in t.files)for(let r in t.files[e]){const s=`${n}/${t.files[e][r].filename}`;await g().remove(s)}}r()}))})(e),await(e=>{e.use(((e,t,n)=>{e.sumor.saveCookie(),e.sumor.response.respond?e.sumor.response.end():e.sumor.response.changed?e.sumor.response.send():n()}))})(e),await(async e=>{const t=`${e.sumor.root}/static`,n=`${Me()}/template`;if(e.use(Ce()({filter:function(){return!0},flush:Fe().Z_SYNC_FLUSH})),await g().exists(n)&&e.use(je()(n)),await g().exists(t)&&e.use(je()(t)),await g().exists(t+"/404.html")){const n=await g().readFile(t+"/404.html","utf-8");e.use(((e,t,r)=>{t.set("Content-Type","text/html;charset=utf-8"),t.send(n)}))}else if(await g().exists(t+"/index.html")){const n=await g().readFile(t+"/index.html","utf-8");e.use(((e,t,r)=>{t.set("Content-Type","text/html;charset=utf-8"),t.send(n)}))}})(e)})(e),e.sumor.logger.trace("后置中间件加载完成"),e.sumor.meta.event.serve&&e.sumor.meta.event.serve.program(e.sumor),await(async e=>{if("https"===e.sumor.protocol){let t;if(443===e.sumor.port){const n=He().createServer((function(e,t){let n=`https://${e.headers.host}${e.url}`;t.writeHead(301,{Location:n}),t.end()}));t=await new Promise((e=>{n.listen(80,(()=>{e(Je(n))}))})),e.sumor.logger.info("http服务已启动,访问将跳转至https")}const n=Ge().createServer({...e.sumor.ssl},e);n.on("error",(t=>{e.sumor.logger.error(t,t.stack)}));const r=await new Promise((t=>{n.listen(e.sumor.port,(()=>{t(Je(n))}))}));e.sumor.close=async()=>{e.sumor.logger.info("正在终止网页服务"),t&&await t(),await r(),e.sumor.logger.info("网页服务已停止运行")}}else{const t=He().createServer(e),n=await new Promise((n=>{t.listen(e.sumor.port,(()=>{n(Je(t))}))}));e.sumor.close=async()=>{e.sumor.logger.info("正在终止网页服务"),await n(),e.sumor.logger.info("网页服务已停止运行")}}})(e),e.sumor.meta.event.served&&e.sumor.meta.event.served.program(e.sumor),e.sumor.logger.info(`应用已运行在 ${e.sumor.origin}`)},We=require("commander");var Ze=n.n(We);const Ye=require("child_process"),Xe=async(e,t,n)=>await new Promise(((r,s)=>{const a=(0,Ye.exec)(e,t);let o="",i="";const c=e=>e.toString().replace(/\r\n/g,"\n").replace(/\r/g,"\n");a.stdout.on("data",(async e=>{e=c(e),o+=e,n&&n(e)})),a.stderr.on("data",(async e=>{e=c(e),o+=e,i+=e,n&&n(e)})),a.on("close",(async e=>{0!==e?s(i):r(o)}))})),Qe=async e=>{const t=[],n=(await Xe("git branch -vva",{cwd:e})).split("\n");for(let e in n){const r=n[e].split(" ").filter((e=>""!==e));if(r.length>=3){const e={};"*"===r[0]&&(e.current=!0,r.shift()),e.name=r.shift(),e.commit=r.shift(),e.name.indexOf("remotes/origin")>=0&&(e.remote=!0,e.origin=e.name,e.name=e.origin.replace("remotes/origin/","")),t.push(e)}}return t},Ve=async(e,t)=>await Xe(`git ${t}`,{cwd:e}),et=async(e,t)=>{if(!await g().exists(e)){const{name:n,folder:r}=(e=>{const t=e.split("/");return{name:t.pop(),folder:t.join("/")}})(e);await g().ensureDir(r),await Xe(`git clone ${t} ${n}`,{cwd:r})}await Xe("git config user.name builder",{cwd:e}),await Xe("git config user.email builder@dummy.com",{cwd:e}),(await Qe(e)).filter((e=>"1.0"===e.name))[0]?(await Ve(e,"checkout 1.0"),await Ve(e,"pull")):(await Ve(e,"checkout --orphan 1.0"),await Ve(e,"reset --hard"),await(async e=>{await g().writeFile(e+"/.gitignore","# IDE configuration\n.idea\n\n# generated files\nnode_modules\noutput\ndist\ntmp\n\n# system\n.DS_Store"),await g().writeFile(e+"/README.md","")})(e),await Ve(e,"add . -f"),await Ve(e,'commit -m "初始化"'),await Ve(e,"push -f origin 1.0"))},tt=async(e,t)=>{const n=(await Ve(e,`log ${t} --pretty=format:"%H|%ad|%cd|%D|%s" --date=iso-strict-local`)).split("\n"),r=[];for(let e of n){const t=e.split("|"),n=[];let s="";if(t[3]){const e=t[3].split(",");for(let t of e)t.indexOf("tag")>=0&&n.push(t.replace("tag:","").trim())}t[4]&&(s=t[4]),r.push({id:t[0],authorDate:new Date(t[1]),committerDate:new Date(t[2]),tags:n,subject:s})}return r},nt=e=>Math.round(new Date(e).getTime()),rt=async(e,{url:t,username:n,password:r})=>{if(0===t.indexOf("http")){let s=t.split("/");const a=`${s[0]}//${n}:${r}@${s[2]}/${s.slice(3,s.length).join("/")}`,o=`${process.cwd()}/tmp/version/${e}`;return await et(o,a),await(async e=>{await Ve(e,"fetch");const t=await Qe(e),n=/^\d+\.\d+?$/,r=/^\d+\.\d+\.\d+?$/,s={};for(let a of t)if(a.remote&&n.test(a.name)){await Ve(e,"reset --hard HEAD"),await Ve(e,`checkout ${a.origin}`);let t=await tt(e,a.origin);t=t.reverse();let n=0;for(let e of t){let t=!0;for(let o of e.tags)if(r.test(o)){const r=parseInt(o.split(a.name+".")[1],10);isNaN(r)||(s[o]={id:e.id,name:o,authorDate:nt(e.authorDate),committerDate:nt(e.committerDate),beta:!1},r>=n&&(n=r+1),t=!1)}t&&(s[a.name+"."+n]={id:e.id,name:a.name+"."+n,authorDate:nt(e.authorDate),committerDate:nt(e.committerDate),beta:!0})}}return s})(o)}},st=require("node-ssh");var at=n.n(st);class ot{constructor(e){this.config=e}async connect(){if(!this.connection){this.connection=new(at());try{await this.connection.connect(this.config)}catch(e){throw new Error("服务器SSH连接失败")}}}async disconnect(){this.connection&&(this.connection.dispose(),delete this.connection)}async exec(e,t){await this.connect(),(t=t||{}).cwd=t.cwd||"~";const n=await this.connection.execCommand(e,t);if(0===n.code||1===n.code)return n.stdout;throw new Error(n.stderr)}async install(e){let t=!0;try{await this.exec(`dpkg -s ${e}`)}catch(e){t=!1}if(!t)try{await this.connection.exec("apt-get update"),await this.connection.exec(`apt-get install ${e} -y`)}catch(e){throw new Error(`服务器软件安装失败:${e.message}`)}}async uninstall(e){let t=!0;try{await this.exec(`dpkg -s ${e}`)}catch(e){t=!1}if(t)try{await this.exec(`apt-get --purge remove ${e} -y`)}catch(e){throw new Error(`服务器软件卸载失败:${e.message}`)}}addTool(e,t){this[e]=t(this)}}const it=require("archiver");var ct=n.n(it);const lt=require("extract-zip");var ut=n.n(lt);const mt=()=>a().v4().replace(/-/g,""),pt=new class{normalize(e){let t=ne().normalize(e);return t=t.replace(/\\/g,"/"),t}async tmp(e){e=e||"sumor-utils";let t=this.normalize(`${T().tmpdir()}/${e}/${mt()}`);return await this.ensureDir(t),t}async download(e,t){await this.ensureFile(t);const n=g().createWriteStream(t);return(await me()({source:e,method:"GET",responseType:"stream"})).data.pipe(n),await new Promise(((e,t)=>{n.on("finish",e),n.on("error",t)}))}async find(e,t){return t=t||{},await new Promise((function(n){$e()(e,t,(function(e,t){for(let e in t)t[e]=ne().normalize(t[e]),t[e]=t[e].replace(/\\/g,"/");n(t)}))}))}async zip(e,t,n){return await new Promise((function(r,s){let a=g().createWriteStream(t),o=ct()("zip",{zlib:{level:9}});a.on("close",(function(){r()})),o.pipe(a),o.glob("**",{cwd:e,dot:!0,ignore:n||[]}),o.finalize()}))}async unzip(e,t){return e=ne().normalize(e),await new Promise((function(n,r){ut()(e,{dir:t},(function(e){e?r(e):n()}))}))}async exists(e){return await new Promise((function(t){g().access(e,(function(e){t(!e)}))}))}async isDirectory(e){return(await this.info(e)).isDirectory()}async info(e){return await new Promise((function(t,n){g().open(e,"a",(function(e,r){e&&n(e),g().fstat(r,(function(e,s){e&&n(e),g().close(r,(function(){t(s)}))}))}))}))}async move(e,t){await g().move(e,t)}async remove(e){await g().remove(e)}async ensureFile(e){await g().ensureFile(e)}async ensureDir(e){await g().ensureDir(e)}async copy(e,t,n){await g().copy(e,t,n)}async writeFile(e,t){return await this.ensureFile(e),await new Promise(((n,r)=>{g().writeFile(e,t,(e=>{e?r(e):n()}))}))}async appendFile(e,t){return await this.ensureFile(e),await new Promise(((n,r)=>{g().appendFile(e,t,(e=>{e?r(e):n()}))}))}async readFile(e,t){if(await this.exists(e))return await new Promise((function(n){g().readFile(e,t,((e,t)=>{if(e)throw e;n(t)}))}))}async readJson(e){return await this.exists(e)?await g().readJson(e):null}async writeJson(e,t){return await this.ensureFile(e),await g().writeJson(e,t)}};pt.exist=pt.exists,pt.readJSON=pt.readJson,pt.writeJSON=pt.writeJson,pt.delete=pt.remove;const dt=pt,gt=e=>({async tmp(e){e=e||"sumor-utils";const t=dt.normalize(`/tmp/${e}/${mt()}`);return await this.ensureDir(t),t},async ensureDir(t){await e.exec(`mkdir -p ${t}`)},async exists(t){const n=(t=dt.normalize(t)).split("/"),r=n.pop();t=n.join("/");let s=!1;try{let n=await e.exec(`ls ${t}`);n=n.split("\n"),s=n.indexOf(r)>=0}catch(e){}return s},async remove(t){await e.exec(`rm -rf ${t}`)},async delete(t){await e.exec(`rm -rf ${t}`)},async putFolder(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmp.zip`,s=await this.tmp("sumor-utils-ssh"),a=`${s}/tmp.zip`;await dt.zip(e,r),await this.putFile(r,a),await this.ensureDir(t),await this.unzip(a,t),await this.delete(s),await dt.delete(n)},async getFolder(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmp.zip`,s=await this.tmp("sumor-utils-ssh"),a=`${s}/tmp.zip`;await this.zip(e,a),await this.getFile(a,r),await dt.unzip(r,t),await this.delete(s),await dt.delete(n)},putFile:async(t,n)=>(await e.connect(),await e.connection.putFile(t,n)),async writeFile(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmpfile`;await dt.ensureFile(r),await dt.writeFile(r,t),await this.putFile(r,e),await dt.delete(n)},async readFile(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmpfile`;await this.getFile(e,r);const s=await dt.readFile(r,t);return await dt.delete(n),s},getFile:async(t,n)=>(await e.connect(),await e.connection.getFile(n,t)),async zip(t,n){await e.install("zip"),await e.exec(`cd ${t};zip -q -r ${n} ./*`)},async unzip(t,n){await e.install("unzip"),await e.exec(`unzip -o ${t} -d ${n}`)},async info(t){if(await this.exists(t)){const n=(await e.exec(`stat ${t} -c "%X|%Y|%Z"`)).split("|"),r={};return n[0]&&(r.access=parseInt(n[0],10)),n[1]&&(r.modify=parseInt(n[1],10)),n[2]&&(r.change=parseInt(n[2],10)),r}}}),ht=e=>({async isOccupied(t){let n=!0;try{""===await e.exec(`lsof -i:${t}`)&&(n=!1)}catch(e){console.log(e)}return n},async getPort(e){if(e?e++:e=1,e>10)throw new Error("服务器端口获取失败");const t=3e4+Math.floor(1e4*Math.random());return await this.isOccupied(t)?await this.getPort(e):t}}),wt=e=>({execCommand:async t=>(await e.install("docker.io"),await e.exec(t)),async remove(e){try{await this.execCommand(`docker rm -f ${e}`)}catch(e){if(e.message.indexOf("No such container")<0)throw e}},async delete(e){try{await this.execCommand(`docker rm -f ${e}`)}catch(e){if(e.message.indexOf("No such container")<0)throw e}},async run({mode:e,image:t,name:n,folder:r,port:s}){r=r||[],s=s||[];const a=["docker","run"];a.push("-itd");for(let e in r)a.push(`-v ${r[e].from}:${r[e].to}${r[e].readOnly?":ro":""}`);for(let e in s)a.push(`-p ${s[e].from}:${s[e].to}`);return n&&a.push(`--name ${n}`),t&&a.push(`-d ${t}`),a.push(e||"/bin/bash"),await this.execCommand(a.join(" "))},async exec(e,t,n){n=n||{},t=JSON.stringify(t);let r="";return n.interaction?r="-it":n.background&&(r="-itd"),await this.execCommand(`docker exec ${r} ${e} sh -c ${t}`,{options:{pty:!0}})},async export(e,t){await this.execCommand(`docker export ${e} > ${t}`)},async ip(e){return await this.execCommand(`docker inspect --format='{{.NetworkSettings.Gateway}}' ${e}`)},async import({path:e,name:t,version:n}){const r=`${t}:${n}`;if((await this.images()).filter((e=>e.Repository===t&&e.Tag===n))[0])throw new Error(`镜像已存在,如需删除请手工执行命令:docker rmi ${r}`);await this.execCommand(`cat ${e} | docker import - ${r}`)},async images(){return await this._checkInfo("docker images",["Repository","Tag","Size"])},async instances(){const e=await this._checkInfo("docker ps -a",["Names","CreatedAt","Status","Ports","Size"]);for(let t in e){e[t].instanceId=e[t].Names;const n=e[t].CreatedAt.split(" ");n.pop(),e[t].createdTime=new Date(n.join(" "))}return e},async instance(e){return(await this.instances()).filter((t=>t.instanceId===e))[0]},async _checkInfo(e,t){let n=[];for(let e in t)n.push(`{{.${t[e]}}}`);const r=await this.execCommand(`${e} --format "${n.join("|")}"`);let s=[];if(""!==r){let e=r.split("\n");for(let n in e){const r=e[n].split("|"),a={};for(let e=0;e<t.length;e++)a[t[e]]=r[e];s.push(a)}}return s}}),ft=e=>({async install(t){await e.exec(`npm i -g ${t}`)},async start(t,n){try{await e.install("nodejs"),await e.install("npm")}catch(e){console.log(e)}let r=!0;try{await e.exec("pm2 -v")}catch(e){r=!1}r||await e.node.install("pm2"),await e.exec("npm i",{cwd:ne().dirname(n)});try{await e.exec(`pm2 start ${n} --name ${t}`)}catch(n){await e.exec(`pm2 restart ${t}`)}},async stop(t){await e.exec(`pm2 stop ${t}`),await e.exec(`pm2 delete ${t}`)},logs:async t=>await e.exec(`pm2 logs --nostream --lines 1000 ${t}`)}),yt=e=>{const t=new ot(e);return t.addTool("file",gt),t.addTool("port",ht),t.addTool("docker",wt),t.addTool("node",ft),t},_t=async(e,t)=>{await Ve(e,"clean -df"),await Ve(e,`checkout ${t}`)},$t=async({server:e,app:t,env:n,git:r,version:s,domain:a})=>{let o=r.url.split("/");const i=`${o[0]}//${r.username}:${r.password}@${o[2]}/${o.slice(3,o.length).join("/")}`,c=`${process.cwd()}/tmp/build/${t}/${s.name}`,l=`${c}.zip`;if(!await g().exists(l)){console.log(`正在构建源代码到${l}`),await g().ensureDir(`${process.cwd()}/tmp/build`);try{await et(c,i),await _t(c,s.id),await Xe("npm run build",{cwd:c}),await g().remove(c+"/web"),await dt.zip(c,l),await g().remove(c)}catch(e){console.log(e)}}const u=`${process.cwd()}/tmp/env/${t}/${s.name}/${n}`;if(!await g().exists(u)){console.log(`正在配置环境相关代码到${u}`),await dt.unzip(l,u);const e=`${process.cwd()}/assets/${t}/${n}`;await g().exists(e)&&await g().copy(e,u)}const m=yt(e),p=await m.port.getPort(),d=`/usr/sumor-cloud/app/${t}_${n}_${s.name}_${p}`,h=`/tmp/sumor-cloud/log/${t}_${n}`,w=`main_${Date.now()}_${s.name}_${e.name}_${p}.log`;console.log(`正在配置实例代码到${d}`),await m.file.remove(d),await m.file.putFolder(u,d),await m.file.ensureDir(h);const f={app:t,env:n,version:s.name,server:e.name,port:p,upTime:Date.now(),versionTime:s.committerDate},y=`sumor_app_${t}_${n}_${s.name}_${p}`;return console.log(`正在部署实例到容器${y}`),await m.docker.run({image:"node",name:y,folder:[{from:`/usr/sumor-cloud/ssl/${a}`,to:"/usr/sumor/runtime/ssl",readOnly:!0},{from:d,to:"/usr/sumor/source"},{from:h,to:"/tmp/log"}],port:[{from:p,to:443}]}),await m.docker.exec(y,"cp -ra /usr/sumor/source/. /usr/sumor/runtime"),await m.docker.exec(y,`echo '${JSON.stringify(f)}' > /usr/sumor/runtime/instance.json`),console.log("正在安装实例依赖库"),await m.docker.exec(y,"cd /usr/sumor/runtime;npm i"),await m.docker.exec(y,`cd /usr/sumor/runtime;npm run start > /tmp/log/${w} 2>&1;`,{background:!0}),await m.disconnect(),y},Et=e=>{const t=e.split("_");t.shift();const n=t.shift(),r=t.shift(),s=t.shift();let a,o,i;t.length>1?(o=t.shift(),a=parseInt(t.shift())):i=t.shift();let c={type:n,app:r,env:s,port:a,version:o,action:i};for(let e in c)c[e]||delete c[e];return c},St=e=>{let t=typeof e;if(null===e)t="null";else if("object"===t){const n=Object.prototype.toString.call(e);"[object Array]"===n?t="array":"[object RegExp]"===n&&(t="regexp")}return t},vt=(e,t)=>("array"===St(t)&&(t=t.join(" ")),`${e} ${t};`),Tt=e=>{let t=[];for(let n in e)t.push(vt(n,e[n]));return t},xt=e=>{const t=[];for(let n in e)if("array"===St(e[n]))for(let r in e[n])t.push(e[n][r]);else t.push(e[n]);return t},bt=(e,t)=>(t=xt(t),xt([`${e} {`,t.map((e=>`\t${e}`)),"}"])),Ot=e=>{let t;return t=e.instances.length>0?Tt({"proxy_set_header Host":"$host","proxy_set_header X-Real-IP":"$remote_addr","proxy_set_header X-Forwarded-For":"$remote_addr",proxy_pass:`https://${e.name}_stream`}):Tt({root:"/etc/nginx/pages",index:"no_instance.html"}),bt("server",[Tt({listen:e.port+" ssl",server_name:e.domain,access_log:`/tmp/${e.name}_access.log`,error_log:`/tmp/${e.name}_error.log`,ssl_certificate:`ssl/${e.domain}/domain.cer`,ssl_certificate_key:`ssl/${e.domain}/domain.key`,ssl_client_certificate:`ssl/${e.domain}/ca.cer`,ssl_session_timeout:"5m",ssl_ciphers:"ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4",ssl_protocols:"TLSv1 TLSv1.1 TLSv1.2",ssl_prefer_server_ciphers:"on"}),bt("location /",[t])])},Nt=(e,t)=>{(t=t||{}).user=t.user||"root";const n=[];for(let t of e)t.port=t.port||443,t.instances.length>0&&n.push((r=t.name,s=t.instances,bt(`upstream ${r}_stream`,s.map((e=>{const t=["server"];return t.push(e.url),e.down?t.push("down"):e.backup?t.push("backup"):(e.weight&&!isNaN(e.weight)&&t.push(`weight=${e.weight}`),e.try&&!isNaN(e.try)&&(t.push(`max_fails=${e.try}`),e.wait&&!isNaN(e.wait)&&t.push(`fail_timeout=${e.wait}s`))),t.join(" ")+";"}))))),n.push(Ot(t));var r,s;return xt([Tt({user:t.user,worker_processes:1}),bt("events",["worker_connections 1024;"]),bt("http",[vt("proxy_connect_timeout","600s"),vt("proxy_send_timeout","600s"),vt("proxy_read_timeout","600s"),vt("server_tokens","off"),vt("client_max_body_size","10m"),bt("server",["listen 80 default_server;","server_name _;","return 301 https://$host$request_uri;"]),xt(n)])]).join("\n")},It=async(e,t,n,r)=>{const s={};for(let r in e.env)for(let a in e.env[r]){const{domain:o,entry:i}=e.env[r][a];s[i]=s[i]||{},s[i][o]=[];const c=(t[r]||{})[a]||{};let l;for(let e in c)(c[e]||{}).live&&(l=e);for(let t in n){const c=e.server[t],u=n[t].map((e=>Et(e))).filter((e=>e.app===a&&e.env===r&&e.version===l));for(let e of u)s[i][o].push(`${c.iHost||c.host}:${e.port}`)}}for(let t in s){const n=[443,80],a=[];for(let e in s[t]){const n={name:e.replace(".","_"),port:443,domain:e,instances:s[t][e].map((e=>({url:e})))};a.push(n)}const o=Nt(a),i=yt(e.server[t]),c="/usr/sumor-cloud/site";await i.file.ensureDir(c),await i.file.ensureDir(c+"/pages"),await i.file.writeFile(`${c}/nginx.conf`,o);const{noInstancePage:l}={noInstancePage:'<html>\n<head>\n<head>\n<meta charset="UTF-8" />\n<meta name="viewport" content="width=device-width, initial-scale=1.0" />\n<title>应用异常</title>\n</head>\n</head>\n<body>\n<h1>应用暂时无法访问</h1><h3>实例未上线</h3></body>\n</html>'};await i.file.writeFile(`${c}/pages/no_instance.html`,l);const u="sumor_site";if(r&&await i.docker.delete(u),!(await i.docker.instances()).filter((e=>e.instanceId===u))[0]){const e="/usr/sumor-cloud/ssl";await i.file.ensureDir(e),console.log("正在站点实例初始化"),await i.docker.run({image:"nginx",name:u,folder:[{from:`${c}/nginx.conf`,to:"/etc/nginx/nginx.conf"},{from:`${c}/pages`,to:"/etc/nginx/pages"},{from:e,to:"/etc/nginx/ssl"},{from:"/tmp/sumor-cloud/site",to:"/tmp"},{from:"/tmp/sumor-cloud/site-nginx",to:"/var/log/nginx"}],port:n.map((e=>({from:e,to:e})))})}await i.docker.exec(u,"nginx -s stop"),await i.docker.exec(u,"nginx -c /etc/nginx/nginx.conf"),await i.disconnect()}},kt=async(e,t)=>{const n=yt(e);await n.docker.delete(t),await n.disconnect()},Rt=async(e,t,n)=>{const r=yt(e);await r.file.putFolder(n,`/usr/sumor-cloud/ssl/${t}`),await r.disconnect()},Dt=n(147);function At(e,t){return new Promise(((n,r)=>{const s=Dt.createReadStream(e),a=Dt.createWriteStream(t,{flags:"a"});a.on("finish",(()=>{n()})),a.on("error",(e=>{console.error(e),r(e)})),s.pipe(a)}))}const Lt={serve:Ke,cli:()=>{let e=de().readFileSync(Me()+"/package.json","utf-8");e=JSON.parse(e),console.log(`当前使用的轻呈云应用库位于${Me()}`),Ze().program.name(e.name).version(e.version||"0.0.0","-v, --version"),Ze().program.command("run").description("运行应用").action((async e=>{await Ke()})),Ze().program.command("deploy").description("部署").action((async e=>{await(async()=>{try{const e=Date.now();console.log("正在启动部署");const t=await g().readJson(process.cwd()+"/scope.json"),n=await g().readJson(process.cwd()+"/scale.json");for(let e in t.server)t.server[e].name=e;for(let e in t.env)for(let n in t.env[e]){const{domain:r,entry:s}=t.env[e][n],a=`${process.cwd()}/assets/ssl/${r}`;a&&t.server[s]&&(console.log(`更新${r}域名证书到${s}服务器`),await Rt(t.server[s],r,a))}let r={};for(let e in t.source){console.log(`应用${e}正在检查应用版本`),r[e]=await rt(e,t.source[e]),console.log("应用版本列表");for(let t in r[e])console.log(`- ${t}${r[e][t].beta?" 测试版":""}`);console.log(`应用${e}检查应用版本完成`)}let s=await(async e=>{let t={};for(let n in e.server){const r=yt(e.server[n]);let s=await r.docker.instances();s=s.filter((e=>0===e.instanceId.indexOf("sumor_app"))),t[n]=s.map((e=>e.instanceId)),await r.disconnect()}return t})(t);for(let e in s){console.log(`服务器${e}现存实例列表`);for(let t in s[e])console.log(`- ${s[e][t]}`)}const a={};await g().remove(process.cwd()+"/tmp/env");for(let e in t.env){const o=t.env[e];for(let i in o){const{domain:c}=o[i],l=(n[e]||{})[i]||{};let u;for(let e in l)(l[e]||{}).live&&(u=e);const m=Object.keys(l);for(let r in t.server){const a=s[r].filter((t=>{const n=t.split("_")[4];return 0===t.indexOf(`sumor_app_${i}_${e}`)&&m.indexOf(n)<0}));if(a.length>0){console.log(`正在清除${e}环境应用${i}在服务器${r}中的过期实例`),s[r]=s[r].filter((e=>a.indexOf(e)<0)),await It(t,n,s);for(let e of a)console.log(`清除实例${e}`),await kt(t.server[r],e)}}console.log(`正在部署${e}环境应用${i},上线版本:${u||"无"}`);for(let o in l){const u=l[o]||{};for(let l in u.instance){const m=u.instance[l];console.log(`计划部署${o}版本${m}个实例到${l}服务器`);const p=s[l].filter((t=>0===t.indexOf(`sumor_app_${i}_${e}_${o}`))),d=p.length;if(d<m){const u=m-d;console.log(`当前实例个数:${d},需要扩容${u}个`);for(let m=0;m<u;m++){console.log(`正在扩容第${m+1}个`);const u=r[i][o];if(u.beta&&!a[u.name]){const e=`${process.cwd()}/tmp/build/${i}/${u.name}.zip`;await g().remove(e),a[u.name]=!0}const p=await $t({server:t.server[l],app:i,env:e,git:t.source[i],version:u,domain:c});s[l].unshift(p),await It(t,n,s)}console.log(`扩容${u}个完成`)}else if(d>m){const e=d-m;console.log(`当前实例个数:${d},需要缩减${e}个`);const r=p.slice(m,d);s[l]=s[l].filter((e=>r.indexOf(e)<0)),await It(t,n,s);for(let e of r)await kt(t.server[l],e);console.log(`缩减${e}个完成`)}else console.log("实例数量已符合计划,无需修改")}}console.log(`部署${e}环境应用${i}完成`)}}await It(t,n,s),console.log(`所有应用已完成部署 ${Date.now()-e}ms`)}catch(e){console.log(e)}})()})),Ze().program.command("log [app] [env]").description("查看日志").action((async(e,t,n)=>{await(async(e,t)=>{console.log(`正在打印${e}应用${t}环境的日志`);const n=await g().readJson(process.cwd()+"/scope.json"),r=`/tmp/sumor-cloud/log/${e}_${t}`,s=`${process.cwd()}/tmp/log/${e}_${t}`;await g().ensureDir(s);for(let e in n.server){const t=yt(n.server[e]);await t.file.exists(r)&&await t.file.getFolder(r,s),await t.disconnect()}let a=await dt.find("**",{cwd:s});a.sort(),await g().remove(`${s}.log`),await g().ensureFile(`${s}.log`);for(let e of a)await At(`${s}/${e}`,`${s}.log`)})(e,t)})),Ze().program.parse(process.argv)}}})(),r.default})()));
|
|
2
|
+
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(()=>(()=>{var e={525:e=>{e.exports=__dirname},167:e=>{"use strict";e.exports=require("axios")},147:e=>{"use strict";e.exports=require("fs")}},t={};function n(r){var s=t[r];if(void 0!==s)return s.exports;var a=t[r]={exports:{}};return e[r](a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{"use strict";n.d(r,{default:()=>Lt});const e=require("express");var t=n.n(e);const s=require("uuid");var a=n.n(s);const o=()=>a().v4().replace(/-/g,""),i=require("stream");var c=n.n(i);const l=e=>{let t,n=e;return"string"==typeof e?t=Buffer.from(e):Buffer.isBuffer(e)&&(t=e),t&&(n=new(c().PassThrough),n.end(t)),n};function u(e){return new Promise(((t,n)=>{let r=[];e.on("error",n),e.on("data",(e=>r.push(e))),e.on("end",(()=>t(Buffer.concat(r))))}))}const m=async(e,t)=>{if(e){let n,r;switch(t=t||"stream"){case"string":r=await u(e),n=r.toString();break;case"buffer":n=await u(e);break;default:n=e}return n}return e},p={delay:async e=>new Promise((t=>{setTimeout((()=>{t()}),1e3*e)})),uuid:o,stream:{from:m,to:l},number:{from10to36:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyz".split(""),n=t.length;let r=+e;const s=[];do{let e=r%n;r=(r-e)/n,s.unshift(t[e])}while(r);return s.join("")},from10to62:e=>{const t="0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ".split(""),n=t.length;let r=+e;const s=[];do{let e=r%n;r=(r-e)/n,s.unshift(t[e])}while(r);return s.join("")},from62to10:e=>{let t=(e=String(e)).length,n=0,r=0;for(;n<t;)r+=Math.pow(62,n++)*"0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ".indexOf(e.charAt(t-n)||0);return r},from36to10:e=>{let t=(e=String(e)).length,n=0,r=0;for(;n<t;)r+=Math.pow(36,n++)*"0123456789abcdefghigklmnopqrstuvwxyz".indexOf(e.charAt(t-n)||0);return r}}},d=require("fs-extra");var g=n.n(d);const h=(e,t)=>(n,r,s)=>{let a,o;if(r=r||{},""!==(s=s||t)){const e=s.split("-");a=e[0],o=e[1]}if(n){const t=n.split("."),i=t.pop(),c=t.join(".");let l;return e[c]&&(o&&(l=(e[c][s]||{})[i]),!l&&a&&(l=(e[c][a]||{})[i]),l||(l=(e[c][""]||{})[i])),((e,t)=>{t=t||{};const n=(e=e||"").match(new RegExp(/\${.*?}/,"g"));if(n)for(let r of n){const n=t[r.substr(2,r.length-3)]||"";e=e.replace(r,n)}return e})(l,r)}{const t={};for(let n in e){const r=e[n][""]||{};let i={},c={};a&&(i=e[n][a]||{}),o&&(c=e[n][s]||{});const l=Object.assign({},r,i,c);for(let e in l)t[`${n}.${e}`]=l[e]}return t}},w=require("chalk");var f=n.n(w);const y={trace:"#7f8c8d",debug:"#2980b9",info:"#2ecc71",warn:"#f39c12",error:"#c0392b"};let _="debug",$=!1;const E=class{constructor(e,t){e=e||"DEFAULT";const n=["trace","debug","info","warn","error"];for(let r of n)this[r]=function(){const n=Array.from(arguments),s=["#",(new Date).toISOString(),r.toUpperCase(),e.toUpperCase()];t&&""!==t&&s.push(t),s.push("-");const a=`${s.join(" ")}`;$?n.unshift(a):n.unshift(f().hex(y[r]).visible(a)),console.log.apply(null,n)}}static setProduction(e){e&&($=!!e)}static setLevel(e){e&&(_=e)}static getLevel(){return _}};let S=0;const v=require("os");var T=n.n(v);const x=1e3*(Math.floor(Date.now()/1e3)-T().uptime()),b=Date.now(),O=e=>Math.round(e),N={serverUpTime:x,serviceUpTime:b,interval:60,memory:[],cpu:[]};let I;const k=async()=>{N.updateTime=Date.now();const e={time:Date.now(),idle:T().cpus().map((e=>e.times.idle))};if(I){const t=((e,t)=>{const n=t.time-e.time;let r=0;for(let s in t.idle){let a=(t.idle[s]-e.idle[s])/n;a>1&&(a=1),a=100-100*a,r+=a}return O(r/t.idle.length)})(I,e);N.cpu.unshift(t),N.cpu=N.cpu.slice(0,1440)}I=e,N.memory.unshift(O((T().totalmem()-T().freemem())/T().totalmem()*100)),N.memory=N.memory.slice(0,1440)},R=require("body-parser");var D=n.n(R);const A=require("multer");var L=n.n(A);const C=require("cookie-parser");var q=n.n(C);const F=require("knex");var P=n.n(F);const j=e=>{const t={};switch((e=e||{}).type=e.type||"better-sqlite3",e.type){case"sqlite":case"sqlite3":case"better-sqlite3":t.client="better-sqlite3";break;case"mysql":case"mysql2":t.client="mysql2";break;default:throw new Error(`不支持数据库类型${e.type}`)}switch(t.client){case"better-sqlite3":t.connection={filename:e.path||process.cwd()+"/main.sqlite"},t.useNullAsDefault=!0;break;case"mysql2":t.connection={host:e.host,port:e.port||3306,user:e.user,password:e.password,database:e.database,charset:e.charset||"utf8mb4"},t.pool=e.pool||{min:2,max:10}}return t};class z{constructor(e,t){this.config=e,this._config=j(e),this._logger=t||{debug:console.log,trace:console.log}}async ensure(){let e,t,n,r,s;switch(this._config.client){case"better-sqlite3":await g().ensureFile(this._config.connection.filename);break;case"mysql2":e=Object.assign({},this.config),t=e.database,delete e.database,n=P()(j(e)),r=await n.raw("show databases"),s=!!r[0].filter((e=>e.Database===t))[0],s||(this._logger.trace("数据库不存在,正在创建"),await n.raw(`CREATE DATABASE IF NOT EXISTS ${t} default charset utf8mb4 COLLATE utf8mb4_general_ci`),this._logger.trace("数据库创建完成")),await new Promise((e=>{n.destroy((function(){e()}))}));break;default:this._logger.trace(`暂不支持${this._config.client}类型数据库创建,请自行确认数据库存在`)}}async connect(){this.knex||(this.knex=P()(this._config))}async destroy(){this.knex&&(await new Promise((e=>{this.knex.destroy((function(){e()}))})),delete this.knex)}}const M=(e,t)=>{t=t||"-";const n=[];for(let t=0;t<e.length;t++){const s=e.charAt(t),a=s.toLowerCase();0===n.length?n.push(a):((r=s)>="A"&&r<="Z"&&n.push(""),n[n.length-1]=n[n.length-1]+=a)}var r;return n.join(t)},B=(e,t,n,r)=>{let s;switch(n.type=n.type||"string",n.type){case"string":n.length=n.length||255;break;case"number":n.length=n.length||10}if(n.increment)s=e.increments(t);else{let r;switch((e=>{const t=e.length;let n;switch(e.type){case"string":n=t>1e3?"text":"string";break;case"number":n=t>18?"string":null!==e.scale&&void 0!==e.scale?"double":t>9?"bigInteger":t>4?"integer":t>2?"smallint":"tinyint"}return n})(n)){case"tinyint":s=e.tinyint(t),r="number";break;case"smallint":s=e.smallint(t),r="number";break;case"integer":s=e.integer(t),r="number";break;case"bigInteger":s=e.bigInteger(t),r="number";break;case"string":s=e.string(t,n.length),r="string";break;case"text":s=e.text(t,n.length),r="string";break;case"double":s=e.double(t,n.length,n.scale),r="number"}if(null!==n.default){let e;"number"===r?(void 0===n.default&&(n.default=0),e=parseInt(n.default,10)):(void 0===n.default&&(n.default=""),e=n.default.toString()),s.defaultTo(e)}n.notNull&&s.notNullable()}n.key&&s.primary(),r&&s.alter()},H=async(e,t,n)=>{n=n||{};const r={},s=await e.schema.hasTable(t).transacting(e);if(!n.rename&&!n.deleted){let e=!1;for(let t in n.property)n.property[t].key&&(e=!0);e||(r.id={type:"string",length:32});for(let t in n.property)"id"!==t||e?["createdBy","createdTime","updatedBy","updatedTime"].indexOf(t)<0&&(r[t]=n.property[t]):r[t]=n.property[t];let t={type:"number",length:13};if(n.join)for(let e in n.join)r[M(e,"_")+"_id"]={type:"string",length:32};r.createdBy={name:"创建者",type:"string",length:32},r.createdTime={name:"创建时间",...t},r.updatedBy={name:"更新者",type:"string",length:32},r.updatedTime={name:"更新时间",...t}}if(s)if(n.rename){const r=M(n.rename,"_");await e.schema.renameTable(t,r)}else if(n.deleted)await e.schema.dropTable(t);else{let n=await e(t).columnInfo();await e.schema.alterTable(t,(function(e){for(let t in r){const s=M(t,"_"),a=r[t];if(n[s]&&a.rename){const t=M(a.rename,"_");e.renameColumn(s,t)}}})).transacting(e),n=await e(t).columnInfo(),await e.schema.alterTable(t,(function(e){for(let t in r){const s=M(t,"_"),a=r[t];a.rename||(n[s]?a.deleted?e.dropColumn(s):B(e,s,a,!0):a.rename||a.deleted||B(e,s,a))}}))}else n.rename||n.deleted||await e.schema.createTable(t,(function(e){for(let t in r){const n=M(t,"_"),s=r[t];s.rename||s.deleted||B(e,n,s)}})).transacting(e)},U=(e,t,n)=>{t=t||"-";let r=(e=e.toLowerCase()).split(t);e="";for(let t in r){let n=r[t];e+=n.replace(n[0],n[0].toUpperCase())}return n&&(e=e.replace(e[0],e[0].toLowerCase())),e},G=e=>{let t=typeof e;if(null===e)t="null";else if("object"===t){const n=Object.prototype.toString.call(e);"[object Array]"===n?t="array":"[object RegExp]"===n&&(t="regexp")}return t},J=e=>{const t={};for(let n in e)t[M(n,"_")]=e[n];return t},K=async({config:e,logger:t})=>{t=t||{debug:console.log,trace:console.log};const n=new z(e,t);await n.ensure(),await n.connect();const r={info:{}};return{connect:async(e,t)=>((e,t,n,r)=>{r=r||"";const s={};let a;const i=async function(){a||(a=await e.knex.transaction())};return s.setUser=e=>{r=e,n.trace(`已修改操作用户为${e}`)},s.info=async(e,n)=>{if(!n&&t.info[e])return t.info[e];const r=await a.from(e).columnInfo(),s={};for(let e in r){const t=U(e,"_",!0);let n;switch(r[e].type){case"char":case"varchar":case"text":case"mediumtext":case"":n="string";break;case"tinyint":case"smallint":case"int":case"integer":case"bigint":case"float":case"double":n="number";break;default:n="string",console.log(`未知数据类型 ${e} ${JSON.stringify(r[e])}`)}s[t]={type:n,length:parseInt(r[e].maxLength,10)}}return t.info[e]=s,s},s.count=async(e,t,r)=>{await i(),r=r||{},e=M(e,"_");const s=a.from(e);s.count({count:"*"});let o=!1;if(t){t=J(t);for(let e in t)if("object"===G(t[e]))for(let n in t[e]){const r=n,a=t[e][n];"<>"===r&&null===a?s.whereNotNull(e):s.where(e,r,a)}else null===t[e]?s.whereNull(e):s.where(e,t[e]);o=!0}if(r.term&&""!==r.term&&r.termRange)for(let e in r.termRange){const t=r.termRange[e];0===parseInt(e)?o?s.andWhere(t,"like",`%${r.term}%`):(s.where(t,"like",`%${r.term}%`),o=!0):s.orWhere(t,"like",`%${r.term}%`)}return n.trace(s.toSQL().sql,s.toSQL().bindings),(await s)[0].count},s.single=async(e,t,n)=>{(n=n||{}).top=1;const r=await s.select(e,t,n);return r.length,r[0]},s.select=async(e,t,r)=>{n.trace(`查询${e},条件${JSON.stringify(t)},参数${JSON.stringify(r)}`),await i(),r=r||{},e=M(e,"_");const o=await s.info(e),c=a.from(e);let l=r.field;l&&(l=l.map((e=>M(e,"_")))),c.select(l);let u=!1;if(t){t=J(t);for(let e in t)if("object"===G(t[e]))for(let n in t[e]){const r=n,s=t[e][n];"<>"===r&&null===s?c.whereNotNull(e):c.where(e,r,s)}else null===t[e]?c.whereNull(e):c.where(e,t[e]);u=!0}if(r.term&&""!==r.term&&r.termRange)for(let e in r.termRange){const t=r.termRange[e];0===parseInt(e)?u?c.andWhere(t,"like",`%${r.term}%`):(c.where(t,"like",`%${r.term}%`),u=!0):c.orWhere(t,"like",`%${r.term}%`)}if(!r.sort&&o.createdTime&&(r.sort="created_time DESC"),r.sort)if("string"==typeof r.sort){const e=r.sort.split(",");for(let t in e){let n=e[t].trim();n=n.split(" "),n[0]=M(n[0],"_"),e[t]=n.join(" ")}c.orderByRaw(e.join(","))}else c.orderBy(r.sort);return r.top&&c.limit(r.top),r.skip&&c.offset(r.skip),n.trace(c.toSQL().sql,c.toSQL().bindings),(await c).map((e=>(e=>{const t={};for(let n in e)t[U(n,"_",!0)]=e[n];return t})(e)))},s.insert=async(e,t)=>{t=t||{},e=M(e,"_"),await i();const c=async()=>{const t=o();return 0!==await s.count(e,{id:t})?await c():t};t.id||(t.id=await c()),t.createdBy=r||"",t.createdTime=Date.now(),t.updatedBy=r||"",t.updatedTime=Date.now(),t=J(t);const l=a.insert(t).into(e);return n.trace(l.toSQL().sql,l.toSQL().bindings),await l,t.id},s.update=async(e,t)=>{t=t||{},e=M(e,"_"),await i();const s=t.id;if(delete t.id,null==s)throw new Error("数据ID不存在,无法找到要更新的数据");t.updatedBy=r||"",t.updatedTime=Date.now(),t=J(t);const o=a.update(t).from(e).where({id:s});n.trace(o.toSQL().sql,o.toSQL().bindings),await o},s.modify=async(e,t,r)=>{n.trace(`强制修改${e},数据${JSON.stringify(r)},检查字段${JSON.stringify(t)}`),e=M(e,"_");const a={};for(let e of t)a[M(e,"_")]=r[e];const o=await s.single(e,a,{field:["id"]});let i;return o?(i=o.id,r.id=i,await s.update(e,r)):i=await s.insert(e,r),i},s.ensure=async(e,t,r)=>{n.trace(`确保${e}存在数据${JSON.stringify(r)},检查字段${JSON.stringify(t)}`),e=M(e,"_");const a={};for(let e of t)a[M(e,"_")]=r[e];const o=await s.select(e,a,{field:["id"]});let i;return i=o[0]?o[0].id:await s.insert(e,r),i},s.delete=async(e,t)=>{e=M(e,"_");const r=a.from(e);return t&&(t=J(t),r.where(t)),n.trace(r.toSQL().sql,r.toSQL().bindings),await r.del()},s.sql=async(e,t)=>(await i(),await a.raw(e,t)),s.commit=async()=>{if(a)try{await a.commit(),a=null}catch(e){n.error(e)}},s.rollback=async()=>{if(a)try{await a.rollback(),a=null}catch(e){n.error(e)}},s})(n,r,e,t),destroy:async()=>{await n.destroy()}}},W=async({config:e,logger:t,entity:n,view:r})=>{t=t||{debug:console.log,trace:console.log};const s=new z(e,t);await s.ensure(),await s.connect();const a=await s.knex.transaction();try{for(let e in n){const r=M(e,"_");t.debug(`正在安装实体${e}为${r}`),await H(a,r,n[e]),t.debug(`正在安装实体${e}完成`)}for(let e in r){const t=M(e,"_");await a.schema.dropViewIfExists(t)}const e=((e,t)=>{t=!!t;const n={};for(let t in e)n[M(t,"_")]=e[t];const r=(e=>{let t={};for(let n in e)t[n]=e[n].sql;return t})(n),s=(e=>{let t={};const n=t=>{if(0===e[t].length)return 1;{let r=1;for(let s in e[t])r+=n(e[t][s]);return r}};for(let r in e)t[r]=n(r);return t})((e=>{let t={};for(let n in e){t[n]=[];for(let r in e){let s=e[r].toLowerCase();s=s.replace(/`/g,""),s=s.replace(/\n/g," "),s=s.replace(/ {2}/g," "),s=s.replace(/ {2}/g," "),s=s.replace(/ {2}/g," "),(s.indexOf(` from ${n} `)>=0||s.indexOf(` join ${n} `)>=0)&&t[n].push(r)}}let n={};for(let r in e){n[r]=[];for(let e in t)t[e].indexOf(r)>=0&&n[r].push(e)}return n})(r)),a=((e,t)=>{let n=[];for(let t in e)n.push({name:t,index:e[t]});n=n.sort(((e,t)=>e.index>t.index?1:-1)),t&&(n=n.reverse());let r=[];for(let e in n)r.push(n[e].name);return r})(s,t);let o={};for(let e in a)o[U(a[e],"_")]=n[a[e]];return o})(r);for(let n in e){const r=M(n,"_");t.debug(`正在安装视图${n}为${r}`),await a.schema.createViewOrReplace(r,(function(t){t.as(e[n].sql)})),t.debug(`正在安装视图${n}完成`)}await a.commit()}catch(e){await a.rollback()}await s.destroy()},Z=async(e,t)=>{let n;if("redis"===(e.type||"sqlite")){const e={};n=t=>({get:async(t,n)=>(e[t]||{})[n],set:async(t,n,r)=>{e[t]=e[t]||{},e[t][n]=r}})}else{await W({config:e,logger:t,entity:{cache:{property:{namespace:{type:"string",length:100,notNull:!0},key:{type:"string",length:500,notNull:!0},value:{type:"string",length:1e4,notNull:!0}}}}});const r=await K({config:e,logger:t});n=e=>({get:async(t,n)=>{const s=await r.connect(e),a=await s.single("cache",{namespace:t,key:n});if(await s.commit(),a)return e.trace(`读取缓存${t} ${n}。数据为${a.value}`),a.value;e.trace(`读取缓存${t} ${n}。数据为空`)},set:async(t,n,s)=>{const a=await r.connect(e);try{s?await a.modify("cache",["namespace","key"],{namespace:t,key:n,value:s}):await a.delete("cache",{namespace:t,key:n}),await a.commit(),e.trace(`写入缓存${t} ${n}成功。数据为${s}`)}catch(r){await a.rollback(),e.trace(`写入缓存${t} ${n}失败。数据为${s}`),e.error(r)}}})}return n};class Y{constructor(e){this.req=e,this._id=e.sumor.cookie.t,this._user=null,this._permission={},this._data={},this._time=0}async update({user:e,data:t,permission:n}){e&&(this._user=e,this.req.sumor.db&&this.req.sumor.db.setUser(e)),n&&(this._permission=n),t&&(this._data=t),await this.save()}get id(){return this._id||""}set id(e){throw new Error("sumorApp.TOKEN_ID_EDIT_FORBIDDEN_DIRECTLY")}get time(){return this._time||""}set time(e){throw new Error("sumorApp.TOKEN_TIME_EDIT_FORBIDDEN_DIRECTLY")}get data(){return this._data||{}}set data(e){throw new Error("sumorApp.TOKEN_DATA_EDIT_FORBIDDEN_DIRECTLY")}get user(){return this._user||""}set user(e){throw new Error("sumorApp.USER_EDIT_FORBIDDEN_DIRECTLY")}get permission(){return this._permission}set permission(e){throw new Error("sumorApp.PERMISSION_EDIT_FORBIDDEN_DIRECTLY")}async setData(e,t){this._data[e]=t,await this.save()}async setPermission(e,t){if(e){let n={};if("string"==typeof e)n[e]=t||[];else if("array"===G(e))for(let t of e)n[t]=[];else n=e;for(let e in n)this._permission[e]=this._permission[e]||[],this._permission[e]=this._permission[e].concat(n[e]);await this.save()}}has(e,t){let n=!1;return this._permission[e]&&(t?this._permission[e].indexOf(t)>=0&&(n=!0):n=!0),n}check(e,t){if(!this.user)throw new Error("sumorApp.LOGIN_EXPIRED");if(e){let n,r=[];const s=(e,t)=>{t?r.push(`${e}-${t}`):r.push(`${e}`)};if("string"==typeof e)n=this.has(e,t),n||s(e,t);else for(let t in e){const r=e[t];"string"==typeof r?(n=this.has(r,""),n||s(r,"")):(n=this.has(r.key,r.value),n||s(r.key,r.value))}const a=r.length>0;if(r.length>0){const e=new Error("sumorApp.PERMISSION_DENIED");throw e.data={auth:r.join(",")},e}return a}}async destroy(){""!==this.id&&(await this.req.sumor.cache.set("token",this.id,void 0),delete this.req.sumor.cookie.t)}async load(){if(""!==this.id){let e=await this.req.sumor.cache.get("token",this.id);e?(e=JSON.parse(e),this._user=e.user||null,this._time=e.time||0,this._data=e.data||{},this._permission=e.permission||{}):(this._id=null,this.req.sumor.cookie.t=this._id)}}async save(){this._id||(this._id=o(),this.req.sumor.cookie.t=this._id),await this.req.sumor.cache.set("token",this._id,JSON.stringify({user:this.user,data:this.data,permission:this._permission,time:Date.now()}))}}class X{constructor(e,t){this.req=e,this.res=t,this.respond=!1,this._changed=!1,this._hasError=!1,this._code="OK",this._message="",this._data=null}set code(e){const t=this.req.sumor.text(e,this._data);e&&t?(this._code=e,this._message=t):(this._code="sumorApp.NETWORK_ERROR",this._message=this.req.sumor.text(this._code))}get code(){return this._code}set message(e){this._message=e}get message(){return this._message}set data(e){this._data=e,this._changed=!0}get data(){return this._data}set changed(e){this._changed=e}get changed(){return this._changed}error(e){this.code=e,this._hasError=!0}end(){if(void 0!==this._data)try{this.res.send(this._data)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}}send(){const e={code:this._code,message:this._message,data:this._data};if(this._hasError)try{this.res.status(500),"html"===this.req.accepts(["html","json"])?this.res.send((({title:e,code:t,desc:n,data:r})=>`<html>\n<head>\n<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">\n<style type="text/css">\nhtml{\n background: #273343;\n color: #fff;\n text-align: center;\n padding: 30px;\n}\n.title{\n opacity: .6;\n padding-bottom: 10px;\n}\n.content{\n padding-bottom: 10px;\n}\n.showDetail{\n margin-top: 20px;\n color: #03a9f4;\n cursor: pointer;\n}\n.showDetail.show{\n display: none;\n}\n.detailBox{\n position: relative;\n opacity: 0;\n}\n.detailBox.show{\n opacity: 1;\n}\npre{\n border: 1px solid rgba(255,255,255,.6);\n border-radius: 2px;\n text-align: left;\n height: 50%;\n max-width: 500px;\n margin: 0 auto;\n margin-top: 20px;\n overflow: auto;\n padding: 10px;\n}\n.detailMessage{\n font-size: 14px;\n width: fit-content;\n margin: 0 auto;\n margin-top: 5px;\n}\n</style>\n</head>\n<body>\n<h1>${e}</h1>\n<div class="title">错误原因</div>\n<div class="content">${t} ${n}</div>\n<div class="title showDetail" onclick="show()">点击查看详细错误信息</div>\n<div class="detailBox">\n <pre>${JSON.stringify(r,null,4)}</pre>\n <div class="detailMessage">请将该技术信息提供给应用管理员</div>\n</div>\n<script>\nfunction show(){\n var oDiv = document.getElementsByTagName('div')[2];\n oDiv.classList.add('show')\n var oPre = document.getElementsByTagName('div')[3];\n oPre.classList.add('show');\n}\n<\/script>\n</body>\n</html>`)({title:"服务异常,请稍后再试",...e})):this.res.send(e)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}else try{this.res.set("Content-Type","application/json;charset=utf-8"),this.res.send(e)}catch(e){if("ERR_HTTP_HEADERS_SENT"!==e.code)throw e}}}const Q=require("ali-oss");var V=n.n(Q);const ee={resize:{mode:"m",width:"w",height:"h",longer:"l",shorter:"s"},quality:{related:"q",absolute:"Q"},circle:{radius:"r"},blur:{radius:"r",size:"s"}},te=require("path");var ne=n.n(te);const re=require("crypto");var se=n.n(re);class ae{constructor(e,t){if(this._logger=t,e)switch(e.type){case"aliyunOSS":this._instance=new class{constructor(e){this.aliyunOSS=new(V())(e)}async put(e,t){const n=await this.aliyunOSS.putStream(e,t);if(n.res.status>299){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:n.res},e}}async info(e,t){t=t||{};const n={};let r,s;try{if(r=await this.aliyunOSS.get(e,{process:"image/info"}),t.color)try{const t=await this.aliyunOSS.get(e,{process:"image/average-hue"});if(t.content){const e=JSON.parse(t.content.toString());n.color=e.RGB.replace("0x","#")}}catch(e){}}catch(e){if("NoSuchKey"===e.code)return null;s=e.message}if(!s&&r&&r.res.status>299&&(s=r.res),s){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:s},e}const a=JSON.parse(r.content.toString()),o=e=>{if(a[e])return a[e].value};return n.format=o("Format"),n.size=o("FileSize"),n.height=o("ImageHeight"),n.height&&(n.height=parseInt(n.height,10)),n.width=o("ImageWidth"),n.width&&(n.width=parseInt(n.width,10)),n.make=o("LensMake"),n.model=o("LensModel"),n}async get(e,t){let n,r,s;try{r=await this.aliyunOSS.getStream(e,(e=>{let t={};if(e.image){let n=[];for(let t in ee){const r=e.image[t];if(r){let e=[];e.push(t);for(let n in ee[t])r[n]&&e.push(`${ee[t][n]}_${r[n]}`);n.push(e.join(","))}}e.image.format&&n.push(`format,${e.image.format}`),e.image.orient&&n.push("auto-orient,1"),n.length>0&&(t.process=`image/${n.join("/")}`)}return t})(t))}catch(e){"NoSuchKey"!==e.code&&(s=e.message)}if(!s&&r&&r.res.status>299&&(s=r.res),s){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:s},e}return r&&(n=r.stream),n}async delete(e){const t=await this.aliyunOSS.delete(e);if(t.res.status>299){const e=new Error("sumorStorage.STORAGE_INSTANCE_ERROR");throw e.data={msg:t.res},e}}async exists(e){let t=!0;try{await this.aliyunOSS.get(e)}catch(e){if("NoSuchKey"!==e.code)throw new Error("sumorStorage.STORAGE_INSTANCE_ERROR");t=!1}return t}}(e);break;case"file":this._instance=new class{constructor(e){this.config=e,this.root=ne().resolve(process.cwd(),this.config.path)}_getTargetPath(e){return ne().join(this.root,e)}async put(e,t){const n=this._getTargetPath(e);g().ensureFileSync(n),await new Promise((e=>{let r=g().createWriteStream(n,{encoding:"utf8",start:0});t.pipe(r),t.on("end",(function(){e()}))}))}async get(e){const t=this._getTargetPath(e);if(await g().exists(t))return g().createReadStream(t)}async delete(e){const t=this._getTargetPath(e);await g().remove(t)}async exists(e){const t=this._getTargetPath(e);return await g().exists(t)}}(e)}}async put(e,t){if(t=l(t),!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{const n=(e=>{let t={},n=se().createHash("md5"),r=0;return e.on("data",(e=>{r+=e.length})),e.on("data",n.update.bind(n)),e.on("end",(function(){t.length=r,t.hash=n.digest("hex")})),t})(t),r=await this._instance.put(e,t);return n.response=r,n}catch(e){throw new Error("sumorStorage.STORAGE_FILE_SAVE_FAILED")}}async get(e,t){if(t=t||{},!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{const n=await this._instance.get(e,t);return await m(n,t.type)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_READ_FAILED")}}async delete(e){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.delete(e)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_DELETE_FAILED")}}async info(e,t){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.info(e,t)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_INFO_FAILED")}}async exists(e){if(!this._instance)throw new Error("sumorStorage.STORAGE_NOT_CONNECTED");try{return await this._instance.exists(e)}catch(e){throw new Error("sumorStorage.STORAGE_FILE_INFO_FAILED")}}}const oe=require("@alicloud/sms-sdk");var ie=n.n(oe);let ce;class le{constructor(e,t){this._config=e,this._logger=t||{error:console.log,debug:console.log,trace:console.log}}async send(e,t,n,r){const{signName:s,accessKeyId:a,secretAccessKey:o}=this._config;if(this._config&&!this._config.disable){if(ce||(ce=new(ie())({accessKeyId:a,secretAccessKey:o})),86!==t)throw await new Promise((e=>{setTimeout((()=>{e()}),1e3)})),new Error("sumorSMS.MOBILE_PREFIX_NOT_SUPPORT");if(!n.match(/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/))throw new Error("sumorSMS.MOBILE_FORMAT");try{await new Promise(((t,a)=>{ce.sendSMS({PhoneNumbers:n,SignName:s,TemplateCode:e,TemplateParam:JSON.stringify(r)}).then((function(e){let{Code:n}=e;"OK"===n?t():a(n)}),(function(e){e.data?a(e.data.Code):a(e)}))}))}catch(e){const t=new Error("sumorSMS.SMS_SEND_FAILED");throw t.data={msg:e},t}}else this._logger.error(`消息发送功能不可用。需要发送消息${e}给${t} ${n},参数${JSON.stringify(r)}`)}}var ue=n(167),me=n.n(ue),pe=n(147),de=n.n(pe);const ge=require("jsrsasign"),he=18e5;class we{constructor(e,t,n){this._config=e,this._cache=t,this._name=e.name||"",this._logger=n,this._updatingToken=!1,e.pay&&(this.pay=(e=>{const t=`${process.cwd()}/${e.pay.privateKey}`,n=de().readFileSync(t,"utf8"),r=function(e,t="SHA256withRSA"){const r=e.join("\n")+"\n",s=new ge.KJUR.crypto.Signature({alg:t,prvkeypem:n});s.updateString(r);const a=s.sign();return(0,ge.hextob64)(a)},s=async t=>{let n=Math.floor(Date.now()/1e3),s=Math.random().toString(36).substr(2,15);const a=r([t.method.toUpperCase(),t.url,n,s,t.body]);let o={"Content-Type":"application/json",Accept:"application/json",Authorization:`WECHATPAY2-SHA256-RSA2048 mchid="${e.pay.mchId}",nonce_str="${s}",signature="${a}",timestamp="${n}",serial_no="${e.pay.serialNo}"`};try{return(await me()({method:t.method.toUpperCase(),url:"https://api.mch.weixin.qq.com"+t.url,data:t.body,headers:o})).data}catch(e){throw e.response}};return{sign:r,order:async function(t){t.desc=t.desc||"虚拟商品";let n={method:"POST",url:"/v3/pay/transactions/jsapi",body:JSON.stringify({appid:e.key,mchid:e.pay.mchId,description:t.desc,out_trade_no:t.id,notify_url:e.pay.notifyUrl,amount:{total:Math.round(100*t.amount),currency:"CNY"},payer:{openid:t.openId}})};return(await s(n)).prepay_id},check:async function(t){return await s({method:"GET",url:`/v3/pay/transactions/out-trade-no/${t}?mchid=${e.pay.mchId}`})},close:async function(t){let n={method:"POST",url:`/v3/pay/transactions/out-trade-no/${t}/close`,body:JSON.stringify({mchid:e.pay.mchId,out_trade_no:t})};return await s(n)}}})(e))}async call(e,t){let n;try{n=t?await me().post(e,t):await me().get(e)}catch(e){const t=new Error("WECHAT_API_FAILED");throw t.data={msg:"微信服务器连接失败:"+e.message},t}if(n.data.errcode){this._logger.error();const e=new Error("WECHAT_ERROR");throw e.data={msg:n.data.errmsg},e}return n.data}async init(e){this._app=e,this._logger.info(`微信校验文件已启动 /MP_verify_${this._config.verifyCode}.txt`),e.get(`/MP_verify_${this._config.verifyCode}.txt`,((e,t)=>{t.send(this._config.verifyCode)})),await this.getToken(),setInterval((()=>{this._logger.trace("开始检查微信服务授权凭证是否过期"),this.getToken(),this._logger.trace("检查微信服务授权凭证已完成")}),6e4)}async getToken(){const e=async()=>{let e=await this._cache.get("wechatAccessToken",this._name);return e&&(e=JSON.parse(e)),e=e||{},e.time=e.time||0,e};let t=await e();return Date.now()-t.time>he&&(await this._refreshToken(),t=await e()),(!t||!t.token||Date.now()-t.time>he)&&this._logger.error("微信服务授权凭证更新失败"),t.token}async reloadUsers(){let e,t="",n=0,r=[];const s=async()=>{const a=await this.list(t);e||(e=a.total),n+=a.count,r=r.concat(a.data.openid),n<e&&(t=a.next_openid,await s())};await s();const a=[];for(let e of r)a.push(await this.detail(e));return a}async list(e){e=e||"";const t=`https://api.weixin.qq.com/cgi-bin/user/get?access_token=${await this.getToken()}&next_openid=${e}`;return await this.call(t)}async detail(e){const t=`https://api.weixin.qq.com/cgi-bin/user/info?access_token=${await this.getToken()}&openid=${e}`;return await this.call(t)}async sendTemplateMessage(e,t,n,r){const s=await this.getToken();let a={};for(let e in r)a[e]={value:r[e]};const o=`https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${s}`;try{await this.call(o,{touser:e,template_id:t,url:n,data:a}),this._logger.debug(`模版消息已发送给${e},模版${t},数据${JSON.stringify(r)}`)}catch(n){this._logger.error(`给${e}的模版消息发送失败,模版${t},数据${JSON.stringify(r)}`),this._logger.error(n)}}async updateMenu(e){const t=await this.getToken();await this.call(`https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${t}`,e)}async _refreshToken(){if(!this._updatingToken){this._updatingToken=!0,this._logger.info("正在更新微信服务授权凭证");const e=`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this._config.key}&secret=${this._config.secret}`,t=await me().get(e);if(200===t.status){const e={};t.data.access_token?(e.token=t.data.access_token,e.time=Date.now(),this._logger.info("微信服务授权凭证已更新"),this._logger.info(`授权凭证: ${e.token}`),await this._cache.set("wechatAccessToken",this._name,JSON.stringify(e))):this._logger.error(t.data)}else this._logger.error(t.data);this._updatingToken=!1}}}const fe=e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.type=e.type||"any",e.placeholder=e.placeholder||"",e.required=!0===e.required,e.length=e.length||0,e.rule=e.rule||[],e.helper=e.helper||{},"string"===e.type&&(e.trim=!1!==e.trim,e.upperCase=!0===e.upperCase,e.lowerCase=!0===e.lowerCase),e),ye={text:e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.origin=e.origin||{},e.target=e.target||{},e),rule:e=>((e=e||{}).name=e.name||"",e.desc=e.desc||"",e.text=e.text||"",e.expression=e.expression||"",e),type:fe,entity:(e,t,n)=>{(e=e||{}).name=e.name||"",e.desc=e.desc||"",e.property=e.property||{};for(let r in e.property){const s=e.property[r].type;s&&t.type[s]?(e.property[r]=Object.assign({},t.type[s],e.property[r]),e.property[r].type=t.type[s].type):e.property[r]=fe(e.property[r]),t.type[`${n}.${r}`]=e.property[r]}return e.join=e.join||{},e},program:(e,t)=>{(e=e||{}).name=e.name||"",e.desc=e.desc||"",e.parameters=e.parameters||{};for(let n in e.parameters){const r=e.parameters[n].type;r&&t.type[r]?(e.parameters[n]=Object.assign({},t.type[r],e.parameters[n]),e.parameters[n].type=t.type[r].type):e.parameters[n]=fe(e.parameters[n])}return e}},_e=require("glob");var $e=n.n(_e);const Ee=async({condition:e,options:t})=>(t=t||{},await new Promise((function(n){$e()(e,t,(function(e,t){for(let e in t)t[e]=ne().normalize(t[e]),t[e]=t[e].replace(/\\/g,"/");n(t)}))}))),Se=e=>{let t=e.split("/"),n=t.pop().split("."),r=n.pop(),s=n.shift(),a=null;n.length>0&&(a=n.pop());const o=[...t,s].join(".");return{path:o,route:"/api/"+o.replace(/\./g,"/"),name:s,suffix:r,type:a}},ve=async(e,t,n)=>{const r={};if(await g().exists(e)){const s=t?`**/**.${t}.json`:"**/**.json",a=await Ee({condition:s,options:{cwd:e}});for(let t of a){const n=`${e}/${t}`;r[Se(t).path]=await g().readJson(n)}if(n&&"json"!==n){const s=t?`**/**.${t}.${n}`:`**/**.${n}`,a=await Ee({condition:s,options:{cwd:e}});for(let t of a){const n=`${e}/${t}`,s=Se(t);r[s.path]=r[s.path]||{},r[s.path][s.suffix]=await g().readFile(n,"utf-8")}}}return r},Te={sumorApp:{name:"轻呈云应用文本",origin:{INTERNAL_ERROR:"程序内部错误,请稍后重试,或联系管理员",NETWORK_ERROR:"网络错误,请稍后重试,或联系管理员",PERMISSION_DENIED:"没有访问该功能权限,请联系管理员。缺少权限:${auth}",LOGIN_EXPIRED:"登陆授权失效,请重新登陆",PERMISSION_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改permission,请使用setPermission",LOGIN_STATUS_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改登录状态",USER_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改user,请使用setUser",TOKEN_ID_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌ID,请使用setID",TOKEN_TIME_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌时间",TOKEN_DATA_EDIT_FORBIDDEN_DIRECTLY:"禁止直接修改令牌数据",LACK_USER_ID:"缺少用户ID",AUTH_ERROR:"授权失败,请稍后重试",AUTH_ERROR_COOKIE_MISSING:"cookie丢失",API_NOT_FOUND:"接口未找到",INVALID_PARAMETER:"无效数据:${msg}",RULE_LOGIC_NOT_FUNCTION:"规则逻辑不是有效函数方法",SUFFIX_REQUIRED:"转换为对象缺少必要的后缀名",PATH_ARROGATION:"路径越级",NOT_SUPPORT_ABSOLUTE_PATH:"不支持绝对路径",REQUIRED:"必填项",LENGTH_OUT_OF_LIMIT:"长度必须小于${length}",WECHAT_DISABLED:"微信未启用,请联系管理员"},target:{en:{INTERNAL_ERROR:"Internal program error, please try again later, or contact administrator",NETWORK_ERROR:"Network error. Please try again later or contact the administrator",PERMISSION_DENIED:"You do not have permission ${auth}, please contact administrator",LOGIN_EXPIRED:"Login expired, please login",INVALID_PARAMETER:"Invalid data: ${msg}",RULE_LOGIC_NOT_FUNCTION:"Rule logic isn't valid function",SUFFIX_REQUIRED:"Suffix required for object path",PATH_ARROGATION:"Path arrogation",NOT_SUPPORT_ABSOLUTE_PATH:"Not support absolute path",REQUIRED:"Required",LENGTH_OUT_OF_LIMIT:"The length must be less than ${length}"}}},sumorSMS:{origin:{MOBILE_FORMAT:"手机号格式错误",MOBILE_PREFIX_NOT_SUPPORT:"该国家地区暂未开通服务",SMS_SEND_FAILED:"消息发送失败:${msg}"}},sumorStorage:{name:"轻呈云存储文本",origin:{STORAGE_INSTANCE_ERROR:"存储系统交互异常:${msg}",STORAGE_FILE_SAVE_FAILED:"文件写入失败",STORAGE_NOT_CONNECTED:"未配置存储服务器连接",STORAGE_FILE_READ_FAILED:"文件读取失败",STORAGE_FILE_DELETE_FAILED:"文件删除失败",STORAGE_FILE_INFO_FAILED:"文件获取信息失败"}},sumorDemo:{origin:{DEMO_TEXT_ZH:"演示文本:中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_ZHCN:"演示文本:中国大陆简体中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_ZHHK:"演示文本:中国香港繁体中文,当前语言环境不匹配,已回归原始文本",DEMO_TEXT_EN:"演示文本:英文,当前语言环境不匹配,已回归原始文本"},target:{en:{DEMO_TEXT_EN:"Demo text for english"},zh:{DEMO_TEXT_ZH:"演示文本:中文"},"zh-CN":{DEMO_TEXT_ZHCN:"演示文本:中国大陆简体中文"},"zh-HK":{DEMO_TEXT_ZHHK:"演示文本:中國香港繁體中文"}}}},xe={"sumorApp.term":{name:"查询条件",required:!1},"sumorApp.skip":{name:"跳过条数",type:"number",default:0,required:!1},"sumorApp.top":{name:"条数",type:"number",default:100,required:!1},"sumorApp.sort":{name:"排序规则",type:"string",required:!1}},be={"sumor.language":"sq=阿尔巴尼亚语|Shqip\nsq-AL=阿尔巴尼亚语(阿尔巴尼亚)|Shqiptar (Shqipëri)\ngsw=阿尔萨斯语\ngsw-FR=阿尔萨斯语(法国)\nar=阿拉伯语|العربية\nar-DZ=阿拉伯语(阿尔及利亚)|العربية (الجزائر)\nar-AE=阿拉伯语(阿联酋)|العربية (الإمارات العربية المتحدة)\nar-OM=阿拉伯语(阿曼)|العربية (سلطنة عمان)\nar-EG=阿拉伯语(埃及)|العربية (مصر)\nar-BH=阿拉伯语(巴林)|العربية (البحرين)\nar-QA=阿拉伯语(卡塔尔)|العربية (قطر)\nar-KW=阿拉伯语(科威特)|العربية (الكويت)\nar-LB=阿拉伯语(黎巴嫩)|العربية (لبنان)\nar-LY=阿拉伯语(利比亚)|العربية (ليبيا)\nar-MA=阿拉伯语(摩洛哥)|العربية (المغرب)\nar-SA=阿拉伯语(沙特阿拉伯)|العربية (المملكة العربية السعودية)\nar-TN=阿拉伯语(突尼斯)|العربية (تونس)\nar-SY=阿拉伯语(叙利亚)|العربية (سوريا)\nar-YE=阿拉伯语(也门)|العربية (اليمن)\nar-IQ=阿拉伯语(伊拉克)|العربية (العراق)\nar-JO=阿拉伯语(约旦)|العربية (الأردن)\nam=阿姆哈拉语|አማርኛ\nam-ET=阿姆哈拉语(埃塞俄比亚)|አማርኛ (ኢትዮጵያ)\nas=阿萨姆语|অসমীয়া\nas-IN=阿萨姆语(印度)|অসম (ভাৰত)\naz=阿塞拜疆语|Azərbaycan\naz-Latn=阿塞拜疆语(拉丁语)|Azərbaycan dili (Latın dili)\naz-Latn-AZ=阿塞拜疆语(拉丁语,阿塞拜疆)|Azerbaijani (Latınca, Azerbaijani)\naz-Cyrl=阿塞拜疆语(西里尔文)|Azerbaijani (şirniyyat)\naz-Cyrl-AZ=阿塞拜疆语(西里尔文,阿塞拜疆)|Azerbaijani (Şirniyyat, Azerbaijani)\nkn=埃纳德语\nkn-IN=埃纳德语(印度) \nga=爱尔兰语 \nga-IE=爱尔兰语(爱尔兰) \net=爱沙尼亚语 \net-EE=爱沙尼亚语(爱沙尼亚) \noc=奥克西唐语 \noc-FR=奥克西唐语(法国) \nor=奥里雅语 \nor-IN=奥里雅语(印度) \nba=巴什基尔语 \nba-RU=巴什基尔语(俄罗斯) \neu=巴斯克语 \neu-ES=巴斯克语(巴斯克) \nnso=巴索托语 \nnso-ZA=巴索托语(南非) \nbe=白俄罗斯语 \nbe-BY=白俄罗斯语(白俄罗斯) \nbg=保加利亚语 \nbg-BG=保加利亚语(保加利亚) \nse=北萨米语 \nse-FI=北萨米语(芬兰) \nse-NO=北萨米语(挪威) \nse-SE=北萨米语(瑞典) \nis=冰岛语 \nis-IS=冰岛语(冰岛) \npl=波兰语 \npl-PL=波兰语(波兰) \nbs=波斯尼亚语 \nbs-Latn=波斯尼亚语(拉丁语) \nbs-L=波斯尼亚语(拉丁语,波斯尼亚和黑塞哥维那) \nbs-Cyrl=波斯尼亚语(西里尔文) \nfa=波斯语 \nfa-IR=波斯语 \n布里多尼语\nbr-FR=布里多尼语(法国) \nbo=藏语 \nbo-CN=藏语(中国) \nko=朝鲜语 \nko-KR=朝鲜语(韩国) \ntn=茨瓦纳语 \ntn-ZA=茨瓦纳语(南非) \nprs=达里语 \nprs-AF=达里语(阿富汗) \ntt=鞑靼语 \ntt-RU=鞑靼语(俄罗斯) \nda=丹麦语 \nda-DK=丹麦语(丹麦) \nde=德语 \nde-AT=德语(奥地利) \nde-DE=德语(德国) \nde-LI=德语(列支敦士登) \nde-LU=德语(卢森堡) \nde-CH=德语(瑞士) \ndv=迪维希语 \ndv-MV=迪维希语(马尔代夫) \nru=俄语 \nru-RU=俄语(俄罗斯) \nfo=法罗语 \nfo-FO=法罗语(法罗群岛) \nfr=法语 \nfr-BE=法语(比利时) \nfr-FR=法语(法国) \nfr-CA=法语(加拿大) \nfr-LU=法语(卢森堡) \nfr-MC=法语(摩纳哥) \nfr-CH=法语(瑞士) \nsa=梵语 \nsa-IN=梵语(印度) \nfil=菲律宾语 \nfil-PH=菲律宾语(菲律宾) \nfi=芬兰语 \nfi-FI=芬兰语(芬兰) \nfy=弗里西亚语 \nfy-NL=弗里西亚语(荷兰) \nkm=高棉语 \nkm-KH=高棉语(柬埔寨) \nkl=格陵兰语 \nkl-GL=格陵兰语(格陵兰) \nka=格鲁吉亚语 \nka-GE=格鲁吉亚语(格鲁吉亚) \ngu=古吉拉特语 \ngu-IN=古吉拉特语(印度) \nkk=哈萨克语 \nkk-KZ=哈萨克语(哈萨克斯坦) \nha=豪撒语 \nha-Latn=豪撒语(拉丁语) \nha-Latn-NG=豪撒语(拉丁语,尼日利亚) \nnl=荷兰语 \nnl-BE=荷兰语(比利时) \nnl-NL=荷兰语(荷兰) \nqut=基切语 \nqut-GT=基切语(危地马拉) \nky=吉尔吉斯语 \nky-KG=吉尔吉斯语(吉尔吉斯斯坦) \ngl=加利西亚语 \ngl-ES=加利西亚语(加利西亚语) \nca=加泰罗尼亚语 \nca-ES=加泰罗尼亚语(加泰罗尼亚) \ncs=捷克语 \ncs-CZ=捷克语(捷克共和国) \nco=科西嘉语 \nco-FR=科西嘉语(法国) \n克罗地亚语\nhr-HR=克罗地亚语(克罗地亚) \nhr-B=克罗地亚语(拉丁语,波斯尼亚和黑塞哥维那) \nquz=克丘亚语 \nquz-BO=克丘亚语(玻利维亚) \nquz-EC=克丘亚语(厄瓜多尔) \nquz-PE=克丘亚语(秘鲁) \nkok=孔卡尼语 \nkok-IN=孔卡尼语(印度) \nlv=拉脱维亚语 \nlv-LV=拉脱维亚语(拉脱维亚) \nlo=老挝语 \nlo-LA=老挝语(老挝人民民主共和国) \nlt=立陶宛语 \nlt-LT=立陶宛语(立陶宛) \nlb=卢森堡语 \nlb-LU=卢森堡语(卢森堡) \nrw=卢旺达语 \nrw-RW=卢旺达语(卢旺达) \nro=罗马尼亚语 \nro-RO=罗马尼亚语(罗马尼亚) \nrm=罗曼什语 \nrm-CH=罗曼什语(瑞士) \nsmj=律勒萨米语 \nsmj-NO=律勒萨米语(挪威) \nsmj-SE=律勒萨米语(瑞典) \nmt=马耳他语 \nmt-MT=马耳他语(马耳他) \nmr=马拉地语 \nmr-IN=马拉地语(印度) \nml=马拉雅拉姆语 \nml-IN=马拉雅拉姆语(印度) \nms=马来语 \nms-MY=马来语(马来西亚) \nms-BN=马来语(文莱达鲁萨兰国) \narn=马普丹冈语 \narn-CL=马普丹冈语(智利) \nmk=马其顿语\nmk-MK=马其顿语(前南斯拉夫马其顿共和国) \nmi=毛利语 \nmi-NZ=毛利语(新西兰) \nmn=蒙古语 \nmn-Mong=蒙古语(传统蒙古语) \nmn-Mong-CN=蒙古语(传统蒙古语,中国) \nmn-Cyrl=蒙古语(西里尔文) \nmn-MN=蒙古语(西里尔文,蒙古) \nbn=孟加拉语 \nbn-BD=孟加拉语(孟加拉国) \nbn-IN=孟加拉语(印度) \nmoh=莫霍克语 \nmoh-CA=莫霍克语(莫霍克) \naf=南非荷兰语 \naf-ZA=南非荷兰语(南非) \nsma=南萨米语 \nsma-NO=南萨米语(挪威) \nsma-SE=南萨米语(瑞典) \nne=尼泊尔语 \nne-NP=尼泊尔语(尼泊尔) \nnn-NO=尼诺斯克挪威语(挪威) \nno=挪威语 \nnn=尼诺斯克语\npa=旁遮普语 \npa-IN=旁遮普语(印度) \npt=葡萄牙语 \npt-BR=葡萄牙语(巴西) \npt-PT=葡萄牙语(葡萄牙) \nps=普什图语 \nps-AF=普什图语(阿富汗) \nja=日语 \nja-JP=日语(日本) \nsv=瑞典语 \nsv-FI=瑞典语(芬兰) \nsv-SE=瑞典语(瑞典) \nsr=塞尔维亚语 \nsr-Latn=塞尔维亚语(拉丁语) \nsr-Latn-ME=塞尔维亚语(拉丁语,黑山共和国) \nsr-Latn-RS=塞尔维亚语(拉丁语,塞尔维亚共和国) \nsr-Cyrl=塞尔维亚语(西里尔文) \nsr-Cyrl-ME=塞尔维亚语(西里尔文,黑山共和国) \nsr-Cyrl-RS=塞尔维亚语(西里尔文,塞尔维亚共和国) \nsi=僧伽罗语 \nsi-LK=僧伽罗语(斯里兰卡) \nhsb=上索布语 \nhsb-DE=上索布语(德国) \nnb=书面挪威语 \nnb-NO=书面挪威语(挪威) \nsms=斯科特萨米语 \nsms-FI=斯科特萨米语(芬兰) \nsk=斯洛伐克语 \nsk-SK=斯洛伐克语(斯洛伐克) \nsl=斯洛文尼亚语 \nsl-SI=斯洛文尼亚语(斯洛文尼亚) \nsw=斯瓦希里语 \nsw-KE=斯瓦希里语(肯尼亚) \ngd=苏格兰盖立语 \ngd-GB=苏格兰盖立语(英国) \nxh=索萨语 \nxh-ZA=索萨语(南非) \ntg=塔吉克语 \ntg-Cyrl=塔吉克语(西里尔文) \ntg-Cyrl-TJ=塔吉克语(西里尔文,塔吉克斯坦) \ntzm=塔马塞特语 \ntzm-Latn=塔马塞特语(拉丁语) \ntzm-Latn-DZ=塔马塞特语(拉丁语,阿尔及利亚) \nth=泰国语 \nte=泰卢固语 \nte-IN=泰卢固语(印度) \nta=泰米尔语 \nta-IN=泰米尔语(印度) \nth-TH=泰语(泰国) \ntr=土耳其语 \ntr-TR=土耳其语(土耳其) \ntk=土库曼语 \ntk-TM=土库曼语(土库曼斯坦) \ncy=威尔士语 \ncy-GB=威尔士语(英国) \nug=维吾尔语 \nug-CN=维吾尔语(中国) \nwo=沃洛夫语 \nwo-SN=沃洛夫语(塞内加尔) \nur=乌尔都语 \nur-PK=乌尔都语(巴基斯坦伊斯兰共和国) \nuk=乌克兰语 \nuk-UA=乌克兰语(乌克兰) \nuz=乌兹别克语 \nuz-Latn=乌兹别克语(拉丁语) \nuz-Latn-UZ=乌兹别克语(拉丁语,乌兹别克斯坦) \nuz-Cyrl=乌兹别克语(西里尔文) \nuz-Cyrl-UZ=乌兹别克语(西里尔文,乌兹别克斯坦) \nes=西班牙语 \nes-AR=西班牙语(阿根廷) \nes-PY=西班牙语(巴拉圭) \nes-PA=西班牙语(巴拿马) \nes-PR=西班牙语(波多黎各) \nes-BO=西班牙语(玻利维亚) \nes-DO=西班牙语(多米尼加共和国) \nes-EC=西班牙语(厄瓜多尔) \nes-CO=西班牙语(哥伦比亚) \nes-CR=西班牙语(哥斯达黎加) \nes-HN=西班牙语(洪都拉斯) \nes-US=西班牙语(美国) \nes-PE=西班牙语(秘鲁) \nes-MX=西班牙语(墨西哥) \nes-NI=西班牙语(尼加拉瓜) \nes-SV=西班牙语(萨尔瓦多) \nes-GT=西班牙语(危地马拉) \nes-VE=西班牙语(委内瑞拉玻利瓦尔共和国) \nes-UY=西班牙语(乌拉圭) \nes-ES=西班牙语(西班牙,国际排序) \nes-CL=西班牙语(智利) \nhe=希伯来语 \nhe-IL=希伯来语(以色列) \nel=希腊语 \nel-GR=希腊语(希腊) \ndsb=下索布语 \ndsb-DE=下索布语(德国) \nhu=匈牙利语 \nhu-HU=匈牙利语(匈牙利) \nsyr=叙利亚语 \nsyr-SY=叙利亚语(叙利亚) \nsah=雅库特语 \nsah-RU=雅库特语(俄罗斯) \nhy=亚美尼亚语 \nhy-AM=亚美尼亚语(亚美尼亚) \nig=伊博语 \nig-NG=伊博语(尼日利亚) \nsmn=伊纳里萨米语 \nsmn-FI=伊纳里萨米语(芬兰) \nii=彝语 \nii-CN=彝语(中国) \nit=意大利语 \nit-CH=意大利语(瑞士) \nit-IT=意大利语(意大利) \niu=因纽特语 \niu-Latn=因纽特语(拉丁语) \niu-Latn-CA=因纽特语(拉丁语,加拿大) \niu-Cans=因纽特语(音节) \niu-Cans-CA=因纽特语(音节,加拿大) \nhi=印地语 \nhi-IN=印地语(印度)\nid=印度尼西亚语\nid-ID=印度尼西亚语(印度尼西亚)\nen=英语\nen-IE=英语(爱尔兰)\nen-AU=英语(澳大利亚)\nen-BZ=英语(伯利兹)\nen-PH=英语(菲律宾共和国)\nen-029=英语(加勒比海)\nen-CA=英语(加拿大)\nen-ZW=英语(津巴布韦)\nen-MY=英语(马来西亚)\nen-US=英语(美国)\nen-ZA=英语(南非)\nen-TT=英语(特立尼达和多巴哥)\nen-SG=英语(新加坡)\nen-NZ=英语(新西兰)\nen-JM=英语(牙买加)\nen-IN=英语(印度)\nen-GB=英语(英国)\nyo=约鲁巴语\nyo-NG=约鲁巴语(尼日利亚)\nvi=越南语\nvi-VN=越南语(越南)\nzh=中文\nzh-Hant=中文(繁体)\nzh-MO=中文(繁体,澳门特别行政区)\nzh-TW=中文(繁体,台湾)\nzh-HK=中文(繁体,香港特别行政区)\nzh-CN=中文(简体)\nzh-SG=中文(简体,新加坡)\nzu=祖鲁语\nzu-ZA=祖鲁语(南非)"},Oe=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,cache:c,logger:l,response:u}=e;if(!a.wechat)throw"sumorApp.WECHAT_DISABLED";if(s.data.wechatOpenId)u.respond=!0,n.redirect(o+r.source);else{u.respond=!0;const e={appid:a.wechat.key,redirect_uri:`${o}/wx/authCallback`,response_type:"code",scope:"snsapi_base"};r.source&&(e.redirect_uri=e.redirect_uri+`?target=${encodeURIComponent(r.source)}`);const t=`https://open.weixin.qq.com/connect/oauth2/authorize?${(e=>{let t=[];for(let n in e)t.push([n,e[n]].join("="));return t.join("&")})(e)}#wechat_redirect`;l.trace("获取用户微信授权",t),n.redirect(t)}},Ne=n(167),Ie=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,cache:c,saveCookie:l,logger:u,response:m}=e;if(!a.wechat)throw"sumorApp.WECHAT_DISABLED";{m.respond=!0;const e=`https://api.weixin.qq.com/sns/oauth2/access_token?${(e=>{let t=[];for(let n in e)t.push([n,e[n]].join("="));return t.join("&")})({appid:a.wechat.key,secret:a.wechat.secret,code:r.code,grant_type:"authorization_code"})}`;u.trace("获取用户微信令牌",e);const t=(await Ne.get(e)).data.openid;await s.setData("wechatOpenId",t),l(),n.redirect(o+r.target)}},ke=async(e,t,n)=>{const{data:r,token:s,config:a,origin:o,db:i,logger:c,response:l,tools:u,wechat:m}=e;if(a.wechat){l.respond=!0;const e=r.id,t={appId:a.wechat.key,timeStamp:Math.round(Date.now()/1e3),nonceStr:u.uuid(),package:`prepay_id=${e}`,signType:"RSA"};t.paySign=m.pay.sign([t.appId,t.timeStamp,t.nonceStr,t.package]),n.end(`\n<html>\n<body>\n<h1 id="message">正在启动微信支付,请稍后。如遇到问题,请稍后重试或联系客服。</h1>\n<script>\nfunction onBridgeReady() {\n WeixinJSBridge.invoke('getBrandWCPayRequest', ${JSON.stringify(t)},\n function(res) {\n if (res.err_msg == "get_brand_wcpay_request:ok") {\n // 使用以上方式判断前端返回,微信团队郑重提示:\n //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。\n \n var divElem = document.getElementById('message'); // 获取指定ID的div元素\n divElem.innerHTML = '支付完成'; // 修改div元素中的内容\n setTimeout(function (){\n var target = '${a.wechat.pay.callback||""}';\n if(target&&target!==""){\n window.location.href = target;\n }else{\n var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n if(isChrome) {\n window.location.href = 'about:blank';\n window.close();\n } else {\n window.close();\n }\n }\n },1000);\n }\n });\n}\nif (typeof WeixinJSBridge == "undefined") {\n if (document.addEventListener) {\n document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);\n } else if (document.attachEvent) {\n document.attachEvent('WeixinJSBridgeReady', onBridgeReady);\n document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);\n }\n} else {\n onBridgeReady();\n}\n<\/script>\n</body>\n</html>`)}},Re=async e=>{e.disable("x-powered-by"),e.sumor={app:e,root:process.cwd(),tools:p},await(async e=>{const t=(e=>{const t={monitor:{name:"服务健康状态监控",program:async(e,t,n)=>t.sumor.monitor},text:{name:"当前语言环境文本数据",program:async(e,t,n)=>t.sumor.text()},token:{name:"当前授权登录令牌",program:(e,t,n,r)=>{const s=t.sumor.token;if(s.id){const e=s.data?s.data.nickname:"";return{id:s.id,user:s.user,nickname:e,time:s.time,permission:s.permission}}return{}}},logout:{name:"退出登录",program:async(e,t,n,r)=>{const s=t.sumor.token;s.user&&await s.destroy()}},range:{name:"数据输入范围列表",parameters:{name:{name:"数据名称",desc:"帮助数据的名称",required:!0,type:"string"}},program:async(e,t,n)=>{const r=t.sumor.data.name;return t.sumor.range(r)}},meta:{name:"接口信息",program:async(t,n,r)=>({name:e.sumor.name,instance:e.sumor.instance,api:e.sumorRuntime.exposeApis,text:n.sumor.text()})}};let n={};for(let e in t)n[`sumor.${e}`]=t[e];return n["wx.auth"]={name:"微信授权",parameters:{source:{name:"来源地址",required:!0,type:"string"}},program:Oe},n["wx.authCallback"]={name:"微信授权完成回调",parameters:{code:{name:"微信授权码",required:!0,type:"string"},target:{name:"授权完成跳转地址",required:!0,type:"string"}},program:Ie},n["wx.pay"]={name:"微信支付",program:ke},n})(e),r={};for(let e in t)r[e]={name:t[e].name,parameters:t[e].parameters};const s=["text","rule","type","entity","view","api","event"];let a={range:be,text:Te,type:xe,api:r};for(let t of s){let n=t;a[t]=a[t]||{},"api"!==t&&"event"!==t||(n="program");let r=await ve(`${e.sumor.root}/${t}`,n);if("api"===t){let e={};for(let t in r)e[`api.${t}`]=r[t];r=e}if(a[t]=Object.assign(a[t],r),ye[n])for(let e in a[t])a[t][e]=ye[n](a[t][e],a,e)}await g().ensureDir(`${process.cwd()}/tmp`),await g().writeFile(`${process.cwd()}/tmp/meta.json`,JSON.stringify(a,null,4));for(let e in t)a.api[e]=t[e];const o=await ve(`${e.sumor.root}/view`,"view","sql");for(let e in o)a.view[e]=a.api[e]||ye.program({}),a.view[e]=Object.assign(a.view[e],o[e]);const i=`${e.sumor.root}/api`;if(await g().exists(i)){const e=await Ee({condition:"**/**.js",options:{cwd:i}});for(let t of e){const e=`api.${Se(t).path}`,r=`${i}/${t}`;a.api[e]=a.api[e]||{},a.api[e].program=n.g.globalRequire(r)}}const c=`${e.sumor.root}/event`;if(await g().exists(c)){const e=await Ee({condition:"**/**.js",options:{cwd:c}});for(let t of e){const e=Se(t).path,r=`${c}/${t}`;a.event[e]=a.event[e]||{},a.event[e].program=async t=>{t.logger.debug(`正在执行事件${e}`);let s,a=Object.assign({},t);if(t.db||(s=await t.connectDB(),a=Object.assign(a,{db:s})),n.g.globalRequire)try{await n.g.globalRequire(r)(a||t),s&&await s.commit(),t.logger.debug(`事件${e}完成`)}catch(n){s&&await s.rollback(),t.logger.error(`事件${e}执行失败,${n.message}`),t.logger.trace(n)}else t.logger.error(`事件${e}执行失败,该程序不存在`)}}}e.sumor.meta=a})(e),e.sumorRuntime={},e.use(((e,t,n)=>{e.sumor={cors:!1,ip:e.headers["x-forwarded-for"]||"0.0.0.0",tools:p},n()})),await(async e=>{const t=`${e.sumor.root}/config.json`;let n={};if(await g().exists(t))try{n=await g().readJson(t)}catch(e){}const r=await(async e=>{if(await g().exists(e)){const t={key:await g().readFile(`${e}/domain.key`,"utf-8"),cert:await g().readFile(`${e}/domain.cer`,"utf-8")};return await g().exists(`${e}/ca.cer`)&&(t.ca=await g().readFile(`${e}/ca.cer`,"utf-8")),t}})(`${e.sumor.root}/ssl`);let s=n.protocol||"https";"https"!==s||r||(s="http");const a=n.name||"轻呈云应用",o=n.domain||"localhost",i=parseInt(n.port||("http"===s?80:443),10),c="http"===s&&80===i||"https"===s&&443===i?"":`:${i}`,l=n.origin||`${s}://${o}${c}`,u=n.logLevel||"info",m=n.language||"zh-CN";e.sumor={...e.sumor,name:a,ssl:r,protocol:s,domain:o,port:i,origin:l,logLevel:u,language:m,config:n},e.use(((e,t,r)=>{e.sumor={...e.sumor,protocol:s,domain:o,port:i,origin:l,config:JSON.parse(JSON.stringify(n))},r()}))})(e),await(async e=>{const t=`${e.sumor.root}/instance.json`;let n={};if(await g().exists(t))try{n=await g().readJson(t)}catch(e){}e.sumor.instance=JSON.parse(JSON.stringify(n)),e.use(((e,t,r)=>{if(e.sumor.instance=JSON.parse(JSON.stringify(n)),e.sumor.instance){const{server:n,port:r,upTime:s}=e.sumor.instance;t.set("sumor-instance",`${n}_${r}_${s}`)}r()}))})(e),await(async e=>{e.use(((e,t,n)=>{e.sumor.response=new X(e,t),n()}))})(e),await(e=>{e.use(((t,n,r)=>{const s=(t.get("accept-language")||e.sumor.language).split(","),a=s[0];let o=[];for(let e in s)o.push(s[e].split(";")[0]);t.sumor.language=a,t.sumor.languages=o,r()}))})(e),await(async e=>{const t={};for(let n in e.sumor.meta.text){t[n]=t[n]||{},t[n][""]=e.sumor.meta.text[n].origin||{};for(let r in e.sumor.meta.text[n].target)t[n][r]=e.sumor.meta.text[n].target[r]||{}}e.sumor.text=h(t,e.sumor.language),e.use(((e,n,r)=>{e.sumor.text=h(t,e.sumor.language),r()}))})(e),await(async e=>{e.sumor.range=t=>t?e.sumor.meta.range[t]:e.sumor.meta.range,e.use(((t,n,r)=>{t.sumor.range=e.sumor.range,r()}))})(e),await(e=>{e.use(((e,t,n)=>{e.sumor.timezone=e.get("sumor-timezone"),n()}))})(e),await(e=>{E.setProduction(e.sumor.config.production),E.setLevel(e.sumor.config.logLevel),e.sumor.logger=new E("APP"),e.sumor.logger.info(`日志记录级别:${e.sumor.config.logLevel.toUpperCase()}`),e.sumor.getLogger=e=>new E(e),e.use(((e,t,n)=>{const r=++S,s=e=>new E(e,r);e.sumor.getLogger=s,e.sumor.logger=s("PROGRAM");const a=e.sumor.getLogger("HTTP"),o=e.headers["user-agent"]||"unknown agent";a.trace(`${e.method} ${e.originalUrl} IP/${e.sumor.ip} ${o}`),n()}))})(e),await(async e=>{k(),setInterval((()=>{k()}),6e4),e.use(((e,t,n)=>{e.sumor.monitor=JSON.parse(JSON.stringify(N)),n()}))})(e),await(async e=>{const t=`${e.sumor.root}/tmp/uploads`;await g().ensureDir(t);const n=L()({dest:"tmp/uploads/"});e.uploader=e=>{let t;if(e){let r=[];for(let t in e)"file"===e[t].type&&r.push({name:t});r.length>0&&(t=n.fields(r))}return t},e.use(D().urlencoded({extended:!1})),e.use(D().json()),e.use(D().text())})(e),await(e=>{e.use(q()()),e.use(((e,t,n)=>{e.sumor.cookie=JSON.parse(JSON.stringify(e.cookies)),e.sumor.saveCookie=()=>{for(let n in e.cookies)e.sumor.cookie[n]||t.clearCookie(n);for(let n in e.sumor.cookie)e.sumor.cookie[n]!==e.cookies[n]&&t.cookie(n,e.sumor.cookie[n],{maxAge:31536e6,httpOnly:!0})},n()}))})(e),await(async e=>{const t=e.sumor.config.cache||{},n=e.sumor.getLogger("CACHE"),r=await Z(t,n);e.sumor.cache=r(n),e.use((async(e,t,n)=>{const s=e.sumor.getLogger("CACHE");e.sumor.cache=r(s),n()}))})(e),await(async e=>{e.use((async(e,t,n)=>{e.sumor.token=new Y(e),await e.sumor.token.load(),n()}))})(e),await(async e=>{const t=e.sumor.config.database,n=e.sumor.getLogger("DATABASE");await W({config:t,logger:n,entity:e.sumor.meta.entity,view:e.sumor.meta.view});const r=await K({config:t,logger:n});e.sumor.connectDB=async()=>await r.connect(n),e.use((async(e,t,n)=>{const s=e.sumor.getLogger("DATABASE");e.sumor.connectDB=async()=>await r.connect(s),e.sumor.db=await e.sumor.connectDB(),e.sumor.token.user&&e.sumor.db.setUser(e.sumor.token.user),n()}))})(e),await(async e=>{const t=e.sumor.getLogger("STORAGE");e.sumor.storage=new ae(e.sumor.config.storage,t),e.use(((t,n,r)=>{const s=t.sumor.getLogger("STORAGE");t.sumor.storage=new ae(e.sumor.config.storage,s),r()}))})(e),await(async e=>{if(e.sumor.config.sms){const t=e.sumor.getLogger("SMS");e.sumor.sms=new le(e.sumor.config.sms,t)}e.use(((t,n,r)=>{if(e.sumor.config.sms){const n=t.sumor.getLogger("SMS");t.sumor.sms=new le(e.sumor.config.sms,n)}r()}))})(e),await(async e=>{if(e.sumor.config.wechat){const t=e.sumor.getLogger("WECHAT");let n;t.debug("微信服务器正在启动"),n=e.sumor.config.wechat.cache?(await Z(e.sumor.config.wechat.cache,t))(t):e.sumor.cache,t.trace(`微信服务器配置信息 ${JSON.stringify(e.sumor.config.wechat)}`),e.sumor.wechat=new we(e.sumor.config.wechat,n,t),await e.sumor.wechat.init(e),t.debug("微信服务器已启动"),e.use(((t,n,r)=>{const s=t.sumor.getLogger("WECHAT");t.sumor.wechat=new we(e.sumor.config.wechat,s),r()}))}})(e)},De=(e,t,n)=>{const r="/"+e.replace(/\./g,"/"),s=`${t.sumor.root}/tmp/uploads`;let a=t.uploader(t.sumor.meta.api[e].parameters);return a?t.all(r,a,((e,t,n)=>{const r={};if(e.files)for(let t in e.files){const n=[];for(let r in e.files[t])n.push({name:e.files[t][r].originalname,size:e.files[t][r].size,mime:e.files[t][r].mimetype,encoding:e.files[t][r].encoding,path:`${s}/${e.files[t][r].filename}`});r[t]=n}e.sumor.data=Object.assign({},e.query,e.body,r),n()}),n):t.all(r,((e,t,n)=>{e.sumor.data=Object.assign({},e.query,e.body),n()}),n),!!a},Ae=(e,t)=>{for(let n in t.parameters){const r=t.parameters[n];switch(void 0!==r.default&&("string"===r.type?null!==e[n]&&void 0!==e[n]&&""!==e[n]||(e[n]=r.default):null!==e[n]&&void 0!==e[n]||(e[n]=r.default)),r.type){case"string":null!==e[n]&&void 0!==e[n]&&"string"!=typeof e[n]&&(e[n]=e[n].toString());break;case"number":"number"!=typeof e[n]&&null!==e[n]&&void 0!==e[n]&&("string"==typeof e[n]?(e[n]=parseFloat(e[n]),isNaN(e[n])&&(e[n]=null)):delete e[n])}if(e[n]&&(r.trim&&(e[n]=e[n].trim()),r.upperCase&&(e[n]=e[n].toUpperCase()),r.lowerCase&&(e[n]=e[n].toLowerCase())),!0===r.required&&(void 0===e[n]||null===e[n]||""===e[n]))throw new Error("sumorApp.REQUIRED");if(r.length&&e[n]&&e[n].length>r.length){const e=new Error("sumorApp.LENGTH_OUT_OF_LIMIT");throw e.data={length:r.length},e}for(let t of r.rule)if(!new RegExp(t.expression).test(e[n]))throw new Error(t.text)}return e},Le=require("compression");var Ce=n.n(Le);const qe=require("zlib");var Fe=n.n(qe);const Pe=require("serve-static");var je=n.n(Pe),ze=n(525),Me=n.n(ze);const Be=require("http");var He=n.n(Be);const Ue=require("spdy");var Ge=n.n(Ue);const Je=e=>{const t=[];return e.on("connection",(function(e){t.push(e),e.once("close",(function(){t.splice(t.indexOf(e),1)}))})),async()=>await new Promise((n=>{t.forEach((function(e){e.destroy()})),e.close((function(){n()}))}))},Ke=async()=>{const e=t()();await Re(e),e.sumor.logger.trace("前置中间件加载完成"),e.sumor.meta.event.setup&&e.sumor.meta.event.setup.program(e.sumor),e.sumor.meta.event.prepare&&e.sumor.meta.event.prepare.program(e.sumor),await(async e=>{e.sumorRuntime.exposeApis={};const t=Object.keys(e.sumor.meta.api);t.sort(((e,t)=>e>t?1:-1));for(let n of t){const t="/"+n.replace(/\./g,"/"),r=async function(t,r,s){t.sumor.meta=e.sumor.meta,t.sumor.cors=!0,t.sumor.response.changed=!0,e.sumor.meta.event.context&&e.sumor.meta.event.context.program(t.sumor,t,r);try{const s=e.sumor.meta.api[n];t.sumor.data=Ae(t.sumor.data,s);const a=await s.program(t.sumor,t,r);t.sumor.response.data=a||t.sumor.response.data,await t.sumor.db.commit()}catch(n){try{await t.sumor.db.rollback()}catch(e){}t.sumor.response.error(n.message);let r="";n instanceof Error&&(r=e.sumor.text(n.message)),t.sumor.logger.debug(`外部请求出错:${n.message} ${r}`),t.sumor.logger.trace(n)}s()},s=De(n,e,r);e.sumorRuntime.exposeApis[t]={name:e.sumor.meta.api[n].name||"",desc:e.sumor.meta.api[n].desc||"",parameters:e.sumor.meta.api[n].parameters||{}},e.sumor.logger.info(`接口已就绪:${t}${s?" (允许文件上传)":""}`)}e.sumor.logger.info("所有接口已就绪")})(e),e.sumor.logger.trace("处理程序加载完成"),await(async e=>{await(e=>{e.use(((e,t,n)=>{e.sumor.cors&&(t.header("Access-Control-Allow-Origin","*"),t.header("Access-Control-Allow-Headers","X-Requested-With"),t.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS")),n()}))})(e),await(e=>{e.use((async(t,n,r)=>{if(t.files){const n=`${e.sumor.root}/tmp/uploads`;for(let e in t.files)for(let r in t.files[e]){const s=`${n}/${t.files[e][r].filename}`;await g().remove(s)}}r()}))})(e),await(e=>{e.use(((e,t,n)=>{e.sumor.saveCookie(),e.sumor.response.respond?e.sumor.response.end():e.sumor.response.changed?e.sumor.response.send():n()}))})(e),await(async e=>{const t=`${e.sumor.root}/static`,n=`${Me()}/template`;if(e.use(Ce()({filter:function(){return!0},flush:Fe().Z_SYNC_FLUSH})),await g().exists(n)&&e.use(je()(n)),await g().exists(t)&&e.use(je()(t)),await g().exists(t+"/404.html")){const n=await g().readFile(t+"/404.html","utf-8");e.use(((e,t,r)=>{t.set("Content-Type","text/html;charset=utf-8"),t.send(n)}))}else if(await g().exists(t+"/index.html")){const n=await g().readFile(t+"/index.html","utf-8");e.use(((e,t,r)=>{t.set("Content-Type","text/html;charset=utf-8"),t.send(n)}))}})(e)})(e),e.sumor.logger.trace("后置中间件加载完成"),e.sumor.meta.event.serve&&e.sumor.meta.event.serve.program(e.sumor),await(async e=>{if("https"===e.sumor.protocol){let t;if(443===e.sumor.port){const n=He().createServer((function(e,t){let n=`https://${e.headers.host}${e.url}`;t.writeHead(301,{Location:n}),t.end()}));t=await new Promise((e=>{n.listen(80,(()=>{e(Je(n))}))})),e.sumor.logger.info("http服务已启动,访问将跳转至https")}const n=Ge().createServer({...e.sumor.ssl},e);n.on("error",(t=>{e.sumor.logger.error(t,t.stack)}));const r=await new Promise((t=>{n.listen(e.sumor.port,(()=>{t(Je(n))}))}));e.sumor.close=async()=>{e.sumor.logger.info("正在终止网页服务"),t&&await t(),await r(),e.sumor.logger.info("网页服务已停止运行")}}else{const t=He().createServer(e),n=await new Promise((n=>{t.listen(e.sumor.port,(()=>{n(Je(t))}))}));e.sumor.close=async()=>{e.sumor.logger.info("正在终止网页服务"),await n(),e.sumor.logger.info("网页服务已停止运行")}}})(e),e.sumor.meta.event.served&&e.sumor.meta.event.served.program(e.sumor),e.sumor.logger.info(`应用已运行在 ${e.sumor.origin}`)},We=require("commander");var Ze=n.n(We);const Ye=require("child_process"),Xe=async(e,t,n)=>await new Promise(((r,s)=>{const a=(0,Ye.exec)(e,t);let o="",i="";const c=e=>e.toString().replace(/\r\n/g,"\n").replace(/\r/g,"\n");a.stdout.on("data",(async e=>{e=c(e),o+=e,n&&n(e)})),a.stderr.on("data",(async e=>{e=c(e),o+=e,i+=e,n&&n(e)})),a.on("close",(async e=>{0!==e?s(i):r(o)}))})),Qe=async e=>{const t=[],n=(await Xe("git branch -vva",{cwd:e})).split("\n");for(let e in n){const r=n[e].split(" ").filter((e=>""!==e));if(r.length>=3){const e={};"*"===r[0]&&(e.current=!0,r.shift()),e.name=r.shift(),e.commit=r.shift(),e.name.indexOf("remotes/origin")>=0&&(e.remote=!0,e.origin=e.name,e.name=e.origin.replace("remotes/origin/","")),t.push(e)}}return t},Ve=async(e,t)=>await Xe(`git ${t}`,{cwd:e}),et=async(e,t)=>{if(!await g().exists(e)){const{name:n,folder:r}=(e=>{const t=e.split("/");return{name:t.pop(),folder:t.join("/")}})(e);await g().ensureDir(r),await Xe(`git clone ${t} ${n}`,{cwd:r})}await Xe("git config user.name builder",{cwd:e}),await Xe("git config user.email builder@dummy.com",{cwd:e}),(await Qe(e)).filter((e=>"1.0"===e.name))[0]?(await Ve(e,"checkout 1.0"),await Ve(e,"pull")):(await Ve(e,"checkout --orphan 1.0"),await Ve(e,"reset --hard"),await(async e=>{await g().writeFile(e+"/.gitignore","# IDE configuration\n.idea\n\n# generated files\nnode_modules\noutput\ndist\ntmp\n\n# system\n.DS_Store"),await g().writeFile(e+"/README.md","")})(e),await Ve(e,"add . -f"),await Ve(e,'commit -m "初始化"'),await Ve(e,"push -f origin 1.0"))},tt=async(e,t)=>{const n=(await Ve(e,`log ${t} --pretty=format:"%H|%ad|%cd|%D|%s" --date=iso-strict-local`)).split("\n"),r=[];for(let e of n){const t=e.split("|"),n=[];let s="";if(t[3]){const e=t[3].split(",");for(let t of e)t.indexOf("tag")>=0&&n.push(t.replace("tag:","").trim())}t[4]&&(s=t[4]),r.push({id:t[0],authorDate:new Date(t[1]),committerDate:new Date(t[2]),tags:n,subject:s})}return r},nt=e=>Math.round(new Date(e).getTime()),rt=async(e,{url:t,username:n,password:r})=>{if(0===t.indexOf("http")){let s=t.split("/");const a=`${s[0]}//${n}:${r}@${s[2]}/${s.slice(3,s.length).join("/")}`,o=`${process.cwd()}/tmp/version/${e}`;return await et(o,a),await(async e=>{await Ve(e,"fetch");const t=await Qe(e),n=/^\d+\.\d+?$/,r=/^\d+\.\d+\.\d+?$/,s={};for(let a of t)if(a.remote&&n.test(a.name)){await Ve(e,"reset --hard HEAD"),await Ve(e,`checkout ${a.origin}`);let t=await tt(e,a.origin);t=t.reverse();let n=0;for(let e of t){let t=!0;for(let o of e.tags)if(r.test(o)){const r=parseInt(o.split(a.name+".")[1],10);isNaN(r)||(s[o]={id:e.id,name:o,authorDate:nt(e.authorDate),committerDate:nt(e.committerDate),beta:!1},r>=n&&(n=r+1),t=!1)}t&&(s[a.name+"."+n]={id:e.id,name:a.name+"."+n,authorDate:nt(e.authorDate),committerDate:nt(e.committerDate),beta:!0})}}return s})(o)}},st=require("node-ssh");var at=n.n(st);class ot{constructor(e){this.config=e}async connect(){if(!this.connection){this.connection=new(at());try{await this.connection.connect(this.config)}catch(e){throw new Error("服务器SSH连接失败")}}}async disconnect(){this.connection&&(this.connection.dispose(),delete this.connection)}async exec(e,t){await this.connect(),(t=t||{}).cwd=t.cwd||"~";const n=await this.connection.execCommand(e,t);if(0===n.code||1===n.code)return n.stdout;throw new Error(n.stderr)}async install(e){let t=!0;try{await this.exec(`dpkg -s ${e}`)}catch(e){t=!1}if(!t)try{await this.connection.exec("apt-get update"),await this.connection.exec(`apt-get install ${e} -y`)}catch(e){throw new Error(`服务器软件安装失败:${e.message}`)}}async uninstall(e){let t=!0;try{await this.exec(`dpkg -s ${e}`)}catch(e){t=!1}if(t)try{await this.exec(`apt-get --purge remove ${e} -y`)}catch(e){throw new Error(`服务器软件卸载失败:${e.message}`)}}addTool(e,t){this[e]=t(this)}}const it=require("archiver");var ct=n.n(it);const lt=require("extract-zip");var ut=n.n(lt);const mt=()=>a().v4().replace(/-/g,""),pt=new class{normalize(e){let t=ne().normalize(e);return t=t.replace(/\\/g,"/"),t}async tmp(e){e=e||"sumor-utils";let t=this.normalize(`${T().tmpdir()}/${e}/${mt()}`);return await this.ensureDir(t),t}async download(e,t){await this.ensureFile(t);const n=g().createWriteStream(t);return(await me()({source:e,method:"GET",responseType:"stream"})).data.pipe(n),await new Promise(((e,t)=>{n.on("finish",e),n.on("error",t)}))}async find(e,t){return t=t||{},await new Promise((function(n){$e()(e,t,(function(e,t){for(let e in t)t[e]=ne().normalize(t[e]),t[e]=t[e].replace(/\\/g,"/");n(t)}))}))}async zip(e,t,n){return await new Promise((function(r,s){let a=g().createWriteStream(t),o=ct()("zip",{zlib:{level:9}});a.on("close",(function(){r()})),o.pipe(a),o.glob("**",{cwd:e,dot:!0,ignore:n||[]}),o.finalize()}))}async unzip(e,t){return e=ne().normalize(e),await new Promise((function(n,r){ut()(e,{dir:t},(function(e){e?r(e):n()}))}))}async exists(e){return await new Promise((function(t){g().access(e,(function(e){t(!e)}))}))}async isDirectory(e){return(await this.info(e)).isDirectory()}async info(e){return await new Promise((function(t,n){g().open(e,"a",(function(e,r){e&&n(e),g().fstat(r,(function(e,s){e&&n(e),g().close(r,(function(){t(s)}))}))}))}))}async move(e,t){await g().move(e,t)}async remove(e){await g().remove(e)}async ensureFile(e){await g().ensureFile(e)}async ensureDir(e){await g().ensureDir(e)}async copy(e,t,n){await g().copy(e,t,n)}async writeFile(e,t){return await this.ensureFile(e),await new Promise(((n,r)=>{g().writeFile(e,t,(e=>{e?r(e):n()}))}))}async appendFile(e,t){return await this.ensureFile(e),await new Promise(((n,r)=>{g().appendFile(e,t,(e=>{e?r(e):n()}))}))}async readFile(e,t){if(await this.exists(e))return await new Promise((function(n){g().readFile(e,t,((e,t)=>{if(e)throw e;n(t)}))}))}async readJson(e){return await this.exists(e)?await g().readJson(e):null}async writeJson(e,t){return await this.ensureFile(e),await g().writeJson(e,t)}};pt.exist=pt.exists,pt.readJSON=pt.readJson,pt.writeJSON=pt.writeJson,pt.delete=pt.remove;const dt=pt,gt=e=>({async tmp(e){e=e||"sumor-utils";const t=dt.normalize(`/tmp/${e}/${mt()}`);return await this.ensureDir(t),t},async ensureDir(t){await e.exec(`mkdir -p ${t}`)},async exists(t){const n=(t=dt.normalize(t)).split("/"),r=n.pop();t=n.join("/");let s=!1;try{let n=await e.exec(`ls ${t}`);n=n.split("\n"),s=n.indexOf(r)>=0}catch(e){}return s},async remove(t){await e.exec(`rm -rf ${t}`)},async delete(t){await e.exec(`rm -rf ${t}`)},async putFolder(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmp.zip`,s=await this.tmp("sumor-utils-ssh"),a=`${s}/tmp.zip`;await dt.zip(e,r),await this.putFile(r,a),await this.ensureDir(t),await this.unzip(a,t),await this.delete(s),await dt.delete(n)},async getFolder(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmp.zip`,s=await this.tmp("sumor-utils-ssh"),a=`${s}/tmp.zip`;await this.zip(e,a),await this.getFile(a,r),await dt.unzip(r,t),await this.delete(s),await dt.delete(n)},putFile:async(t,n)=>(await e.connect(),await e.connection.putFile(t,n)),async writeFile(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmpfile`;await dt.ensureFile(r),await dt.writeFile(r,t),await this.putFile(r,e),await dt.delete(n)},async readFile(e,t){const n=await dt.tmp("sumor-utils-ssh"),r=`${n}/tmpfile`;await this.getFile(e,r);const s=await dt.readFile(r,t);return await dt.delete(n),s},getFile:async(t,n)=>(await e.connect(),await e.connection.getFile(n,t)),async zip(t,n){await e.install("zip"),await e.exec(`cd ${t};zip -q -r ${n} ./*`)},async unzip(t,n){await e.install("unzip"),await e.exec(`unzip -o ${t} -d ${n}`)},async info(t){if(await this.exists(t)){const n=(await e.exec(`stat ${t} -c "%X|%Y|%Z"`)).split("|"),r={};return n[0]&&(r.access=parseInt(n[0],10)),n[1]&&(r.modify=parseInt(n[1],10)),n[2]&&(r.change=parseInt(n[2],10)),r}}}),ht=e=>({async isOccupied(t){let n=!0;try{""===await e.exec(`lsof -i:${t}`)&&(n=!1)}catch(e){console.log(e)}return n},async getPort(e){if(e?e++:e=1,e>10)throw new Error("服务器端口获取失败");const t=3e4+Math.floor(1e4*Math.random());return await this.isOccupied(t)?await this.getPort(e):t}}),wt=e=>({execCommand:async t=>(await e.install("docker.io"),await e.exec(t)),async remove(e){try{await this.execCommand(`docker rm -f ${e}`)}catch(e){if(e.message.indexOf("No such container")<0)throw e}},async delete(e){try{await this.execCommand(`docker rm -f ${e}`)}catch(e){if(e.message.indexOf("No such container")<0)throw e}},async run({mode:e,image:t,name:n,folder:r,port:s}){r=r||[],s=s||[];const a=["docker","run"];a.push("-itd");for(let e in r)a.push(`-v ${r[e].from}:${r[e].to}${r[e].readOnly?":ro":""}`);for(let e in s)a.push(`-p ${s[e].from}:${s[e].to}`);return n&&a.push(`--name ${n}`),t&&a.push(`-d ${t}`),a.push(e||"/bin/bash"),await this.execCommand(a.join(" "))},async exec(e,t,n){n=n||{},t=JSON.stringify(t);let r="";return n.interaction?r="-it":n.background&&(r="-itd"),await this.execCommand(`docker exec ${r} ${e} sh -c ${t}`,{options:{pty:!0}})},async export(e,t){await this.execCommand(`docker export ${e} > ${t}`)},async ip(e){return await this.execCommand(`docker inspect --format='{{.NetworkSettings.Gateway}}' ${e}`)},async import({path:e,name:t,version:n}){const r=`${t}:${n}`;if((await this.images()).filter((e=>e.Repository===t&&e.Tag===n))[0])throw new Error(`镜像已存在,如需删除请手工执行命令:docker rmi ${r}`);await this.execCommand(`cat ${e} | docker import - ${r}`)},async images(){return await this._checkInfo("docker images",["Repository","Tag","Size"])},async instances(){const e=await this._checkInfo("docker ps -a",["Names","CreatedAt","Status","Ports","Size"]);for(let t in e){e[t].instanceId=e[t].Names;const n=e[t].CreatedAt.split(" ");n.pop(),e[t].createdTime=new Date(n.join(" "))}return e},async instance(e){return(await this.instances()).filter((t=>t.instanceId===e))[0]},async _checkInfo(e,t){let n=[];for(let e in t)n.push(`{{.${t[e]}}}`);const r=await this.execCommand(`${e} --format "${n.join("|")}"`);let s=[];if(""!==r){let e=r.split("\n");for(let n in e){const r=e[n].split("|"),a={};for(let e=0;e<t.length;e++)a[t[e]]=r[e];s.push(a)}}return s}}),ft=e=>({async install(t){await e.exec(`npm i -g ${t}`)},async start(t,n){try{await e.install("nodejs"),await e.install("npm")}catch(e){console.log(e)}let r=!0;try{await e.exec("pm2 -v")}catch(e){r=!1}r||await e.node.install("pm2"),await e.exec("npm i",{cwd:ne().dirname(n)});try{await e.exec(`pm2 start ${n} --name ${t}`)}catch(n){await e.exec(`pm2 restart ${t}`)}},async stop(t){await e.exec(`pm2 stop ${t}`),await e.exec(`pm2 delete ${t}`)},logs:async t=>await e.exec(`pm2 logs --nostream --lines 1000 ${t}`)}),yt=e=>{const t=new ot(e);return t.addTool("file",gt),t.addTool("port",ht),t.addTool("docker",wt),t.addTool("node",ft),t},_t=async(e,t)=>{await Ve(e,"clean -df"),await Ve(e,`checkout ${t}`)},$t=async({server:e,app:t,env:n,git:r,version:s,domain:a})=>{let o=r.url.split("/");const i=`${o[0]}//${r.username}:${r.password}@${o[2]}/${o.slice(3,o.length).join("/")}`,c=`${process.cwd()}/tmp/build/${t}/${s.name}`,l=`${c}.zip`;if(!await g().exists(l)){console.log(`正在构建源代码到${l}`),await g().ensureDir(`${process.cwd()}/tmp/build`);try{await et(c,i),await _t(c,s.id),await Xe("npm run build",{cwd:c}),await g().remove(c+"/web"),await dt.zip(c,l),await g().remove(c)}catch(e){console.log(e)}}const u=`${process.cwd()}/tmp/env/${t}/${s.name}/${n}`;if(!await g().exists(u)){console.log(`正在配置环境相关代码到${u}`),await dt.unzip(l,u);const e=`${process.cwd()}/assets/${t}/${n}`;await g().exists(e)&&await g().copy(e,u)}const m=yt(e),p=await m.port.getPort(),d=`/usr/sumor-cloud/app/${t}_${n}_${s.name}_${p}`,h=`/tmp/sumor-cloud/log/${t}_${n}`,w=`main_${Date.now()}_${s.name}_${e.name}_${p}.log`;console.log(`正在配置实例代码到${d}`),await m.file.remove(d),await m.file.putFolder(u,d),await m.file.ensureDir(h);const f={app:t,env:n,version:s.name,server:e.name,port:p,upTime:Date.now(),versionTime:s.committerDate},y=`sumor_app_${t}_${n}_${s.name}_${p}`;return console.log(`正在部署实例到容器${y}`),await m.docker.run({image:"node",name:y,folder:[{from:`/usr/sumor-cloud/ssl/${a}`,to:"/usr/sumor/runtime/ssl",readOnly:!0},{from:d,to:"/usr/sumor/source"},{from:h,to:"/tmp/log"}],port:[{from:p,to:443}]}),await m.docker.exec(y,"cp -ra /usr/sumor/source/. /usr/sumor/runtime"),await m.docker.exec(y,`echo '${JSON.stringify(f)}' > /usr/sumor/runtime/instance.json`),console.log("正在安装实例依赖库"),await m.docker.exec(y,"cd /usr/sumor/runtime;npm i"),await m.docker.exec(y,`cd /usr/sumor/runtime;npm run start > /tmp/log/${w} 2>&1;`,{background:!0}),await m.disconnect(),y},Et=e=>{const t=e.split("_");t.shift();const n=t.shift(),r=t.shift(),s=t.shift();let a,o,i;t.length>1?(o=t.shift(),a=parseInt(t.shift())):i=t.shift();let c={type:n,app:r,env:s,port:a,version:o,action:i};for(let e in c)c[e]||delete c[e];return c},St=e=>{let t=typeof e;if(null===e)t="null";else if("object"===t){const n=Object.prototype.toString.call(e);"[object Array]"===n?t="array":"[object RegExp]"===n&&(t="regexp")}return t},vt=(e,t)=>("array"===St(t)&&(t=t.join(" ")),`${e} ${t};`),Tt=e=>{let t=[];for(let n in e)t.push(vt(n,e[n]));return t},xt=e=>{const t=[];for(let n in e)if("array"===St(e[n]))for(let r in e[n])t.push(e[n][r]);else t.push(e[n]);return t},bt=(e,t)=>(t=xt(t),xt([`${e} {`,t.map((e=>`\t${e}`)),"}"])),Ot=e=>{let t;return t=e.instances.length>0?Tt({"proxy_set_header Host":"$host","proxy_set_header X-Real-IP":"$remote_addr","proxy_set_header X-Forwarded-For":"$remote_addr",proxy_pass:`https://${e.name}_stream`}):Tt({root:"/etc/nginx/pages",index:"no_instance.html"}),bt("server",[Tt({listen:e.port+" ssl",server_name:e.domain,access_log:`/tmp/${e.name}_access.log`,error_log:`/tmp/${e.name}_error.log`,ssl_certificate:`ssl/${e.domain}/domain.cer`,ssl_certificate_key:`ssl/${e.domain}/domain.key`,ssl_client_certificate:`ssl/${e.domain}/ca.cer`,ssl_session_timeout:"5m",ssl_ciphers:"ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4",ssl_protocols:"TLSv1 TLSv1.1 TLSv1.2",ssl_prefer_server_ciphers:"on"}),bt("location /",[t])])},Nt=(e,t)=>{(t=t||{}).user=t.user||"root";const n=[];for(let t of e)t.port=t.port||443,t.instances.length>0&&n.push((r=t.name,s=t.instances,bt(`upstream ${r}_stream`,s.map((e=>{const t=["server"];return t.push(e.url),e.down?t.push("down"):e.backup?t.push("backup"):(e.weight&&!isNaN(e.weight)&&t.push(`weight=${e.weight}`),e.try&&!isNaN(e.try)&&(t.push(`max_fails=${e.try}`),e.wait&&!isNaN(e.wait)&&t.push(`fail_timeout=${e.wait}s`))),t.join(" ")+";"}))))),n.push(Ot(t));var r,s;return xt([Tt({user:t.user,worker_processes:1}),bt("events",["worker_connections 1024;"]),bt("http",[vt("proxy_connect_timeout","600s"),vt("proxy_send_timeout","600s"),vt("proxy_read_timeout","600s"),vt("server_tokens","off"),vt("client_max_body_size","10m"),bt("server",["listen 80 default_server;","server_name _;","return 301 https://$host$request_uri;"]),xt(n)])]).join("\n")},It=async(e,t,n,r)=>{const s={};for(let r in e.env)for(let a in e.env[r]){const{domain:o,entry:i}=e.env[r][a];s[i]=s[i]||{},s[i][o]=[];const c=(t[r]||{})[a]||{};let l;for(let e in c)(c[e]||{}).live&&(l=e);for(let t in n){const c=e.server[t],u=n[t].map((e=>Et(e))).filter((e=>e.app===a&&e.env===r&&e.version===l));for(let e of u)s[i][o].push(`${c.iHost||c.host}:${e.port}`)}}for(let t in s){const n=[443,80],a=[];for(let e in s[t]){const n={name:e.replace(".","_"),port:443,domain:e,instances:s[t][e].map((e=>({url:e})))};a.push(n)}const o=Nt(a),i=yt(e.server[t]),c="/usr/sumor-cloud/site";await i.file.ensureDir(c),await i.file.ensureDir(c+"/pages"),await i.file.writeFile(`${c}/nginx.conf`,o);const{noInstancePage:l}={noInstancePage:'<html>\n<head>\n<head>\n<meta charset="UTF-8" />\n<meta name="viewport" content="width=device-width, initial-scale=1.0" />\n<title>应用异常</title>\n</head>\n</head>\n<body>\n<h1>应用暂时无法访问</h1><h3>实例未上线</h3></body>\n</html>'};await i.file.writeFile(`${c}/pages/no_instance.html`,l);const u="sumor_site";if(r&&await i.docker.delete(u),!(await i.docker.instances()).filter((e=>e.instanceId===u))[0]){const e="/usr/sumor-cloud/ssl";await i.file.ensureDir(e),console.log("正在站点实例初始化"),await i.docker.run({image:"nginx",name:u,folder:[{from:`${c}/nginx.conf`,to:"/etc/nginx/nginx.conf"},{from:`${c}/pages`,to:"/etc/nginx/pages"},{from:e,to:"/etc/nginx/ssl"},{from:"/tmp/sumor-cloud/site",to:"/tmp"},{from:"/tmp/sumor-cloud/site-nginx",to:"/var/log/nginx"}],port:n.map((e=>({from:e,to:e})))})}await i.docker.exec(u,"nginx -s stop"),await i.docker.exec(u,"nginx -c /etc/nginx/nginx.conf"),await i.disconnect()}},kt=async(e,t)=>{const n=yt(e);await n.docker.delete(t),await n.disconnect()},Rt=async(e,t,n)=>{const r=yt(e);await r.file.putFolder(n,`/usr/sumor-cloud/ssl/${t}`),await r.disconnect()},Dt=n(147);function At(e,t){return new Promise(((n,r)=>{const s=Dt.createReadStream(e),a=Dt.createWriteStream(t,{flags:"a"});a.on("finish",(()=>{n()})),a.on("error",(e=>{console.error(e),r(e)})),s.pipe(a)}))}const Lt={serve:Ke,cli:()=>{let e=de().readFileSync(Me()+"/package.json","utf-8");e=JSON.parse(e),console.log(`当前使用的轻呈云应用库位于${Me()}`),Ze().program.name(e.name).version(e.version||"0.0.0","-v, --version"),Ze().program.command("run").description("运行应用").action((async e=>{await Ke()})),Ze().program.command("deploy").description("部署").action((async e=>{await(async()=>{try{const e=Date.now();console.log("正在启动部署");const t=await g().readJson(process.cwd()+"/scope.json"),n=await g().readJson(process.cwd()+"/scale.json");for(let e in t.server)t.server[e].name=e;for(let e in t.env)for(let n in t.env[e]){const{domain:r,entry:s}=t.env[e][n],a=`${process.cwd()}/assets/ssl/${r}`;a&&t.server[s]&&(console.log(`更新${r}域名证书到${s}服务器`),await Rt(t.server[s],r,a))}let r={};for(let e in t.source){console.log(`应用${e}正在检查应用版本`),r[e]=await rt(e,t.source[e]),console.log("应用版本列表");for(let t in r[e])console.log(`- ${t}${r[e][t].beta?" 测试版":""}`);console.log(`应用${e}检查应用版本完成`)}let s=await(async e=>{let t={};for(let n in e.server){const r=yt(e.server[n]);let s=await r.docker.instances();s=s.filter((e=>0===e.instanceId.indexOf("sumor_app"))),t[n]=s.map((e=>e.instanceId)),await r.disconnect()}return t})(t);for(let e in s){console.log(`服务器${e}现存实例列表`);for(let t in s[e])console.log(`- ${s[e][t]}`)}const a={};await g().remove(process.cwd()+"/tmp/env");for(let e in t.env){const o=t.env[e];for(let i in o){const{domain:c}=o[i],l=(n[e]||{})[i]||{};let u;for(let e in l)(l[e]||{}).live&&(u=e);const m=Object.keys(l);for(let r in t.server){const a=s[r].filter((t=>{const n=t.split("_")[4];return 0===t.indexOf(`sumor_app_${i}_${e}`)&&m.indexOf(n)<0}));if(a.length>0){console.log(`正在清除${e}环境应用${i}在服务器${r}中的过期实例`),s[r]=s[r].filter((e=>a.indexOf(e)<0)),await It(t,n,s);for(let e of a)console.log(`清除实例${e}`),await kt(t.server[r],e)}}console.log(`正在部署${e}环境应用${i},上线版本:${u||"无"}`);for(let o in l){const u=l[o]||{};for(let l in u.instance){const m=u.instance[l];console.log(`计划部署${o}版本${m}个实例到${l}服务器`);const p=s[l].filter((t=>0===t.indexOf(`sumor_app_${i}_${e}_${o}`))),d=p.length;if(d<m){const u=m-d;console.log(`当前实例个数:${d},需要扩容${u}个`);for(let m=0;m<u;m++){console.log(`正在扩容第${m+1}个`);const u=r[i][o];if(u.beta&&!a[u.name]){const e=`${process.cwd()}/tmp/build/${i}/${u.name}.zip`;await g().remove(e),a[u.name]=!0}const p=await $t({server:t.server[l],app:i,env:e,git:t.source[i],version:u,domain:c});s[l].unshift(p),await It(t,n,s)}console.log(`扩容${u}个完成`)}else if(d>m){const e=d-m;console.log(`当前实例个数:${d},需要缩减${e}个`);const r=p.slice(m,d);s[l]=s[l].filter((e=>r.indexOf(e)<0)),await It(t,n,s);for(let e of r)await kt(t.server[l],e);console.log(`缩减${e}个完成`)}else console.log("实例数量已符合计划,无需修改")}}console.log(`部署${e}环境应用${i}完成`)}}await It(t,n,s),console.log(`所有应用已完成部署 ${Date.now()-e}ms`)}catch(e){console.log(e)}})()})),Ze().program.command("log [app] [env]").description("查看日志").action((async(e,t,n)=>{await(async(e,t)=>{console.log(`正在打印${e}应用${t}环境的日志`);const n=await g().readJson(process.cwd()+"/scope.json"),r=`/tmp/sumor-cloud/log/${e}_${t}`,s=`${process.cwd()}/tmp/log/${e}_${t}`;await g().ensureDir(s);for(let e in n.server){const t=yt(n.server[e]);await t.file.exists(r)&&await t.file.getFolder(r,s),await t.disconnect()}let a=await dt.find("**",{cwd:s});a.sort(),await g().remove(`${s}.log`),await g().ensureFile(`${s}.log`);for(let e of a)await At(`${s}/${e}`,`${s}.log`)})(e,t)})),Ze().program.parse(process.argv)}}})(),r.default})()));
|
package/package.json
CHANGED
|
@@ -1,39 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sumor",
|
|
3
|
-
"version": "1.0.2",
|
|
4
|
-
"description": "Sumor Cloud Application",
|
|
5
|
-
"homepage": "https://www.sumor.com",
|
|
6
|
-
"author": "Sumor Cloud (https://www.sumor.com)",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"bin": {
|
|
9
|
-
"sumor": "cli.js"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@alicloud/sms-sdk": "^1.1.6",
|
|
13
|
-
"ali-oss": "6.1.1",
|
|
14
|
-
"axios": "^1.3.2",
|
|
15
|
-
"better-sqlite3": "^8.0.1",
|
|
16
|
-
"body-parser": "^1.20.1",
|
|
17
|
-
"compression": "^1.7.4",
|
|
18
|
-
"cookie-parser": "^1.4.6",
|
|
19
|
-
"express": "^4.18.2",
|
|
20
|
-
"fs-extra": "^11.1.0",
|
|
21
|
-
"knex": "^2.1.0",
|
|
22
|
-
"chalk": "^4.1.2",
|
|
23
|
-
"multer": "^1.4.2",
|
|
24
|
-
"mysql2": "^3.1.0",
|
|
25
|
-
"redis": "^4.6.4",
|
|
26
|
-
"serve-static": "^1.14.1",
|
|
27
|
-
"spdy": "^4.0.2",
|
|
28
|
-
"uuid": "^3.3.2",
|
|
29
|
-
"glob": "^7.1.2",
|
|
30
|
-
"archiver": "^2.1.1",
|
|
31
|
-
"commander": "^9.4.0",
|
|
32
|
-
"extract-zip": "^1.6.6",
|
|
33
|
-
"node-ssh": "^6.0.0",
|
|
34
|
-
"os-utils": "0.0.14",
|
|
35
|
-
"dayjs": "^1.11.1",
|
|
36
|
-
"vue": "^3.2.37",
|
|
37
|
-
"jsrsasign": "^10.8.6"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
1
|
+
{"name":"sumor","description":"Sumor Cloud Application","homepage":"https://www.sumor.com","author":"Sumor Cloud (https://www.sumor.com)","license":"MIT","bin":{"sumor":"cli.js"},"dependencies":{"@alicloud/sms-sdk":"^1.1.6","ali-oss":"6.1.1","axios":"^1.3.2","body-parser":"^1.20.1","compression":"^1.7.4","cookie-parser":"^1.4.6","express":"^4.18.2","fs-extra":"^11.1.0","knex":"^2.1.0","chalk":"^4.1.2","multer":"^1.4.2","mysql2":"^3.1.0","serve-static":"^1.14.1","spdy":"^4.0.2","uuid":"^3.3.2","glob":"^7.1.2","archiver":"^2.1.1","commander":"^9.4.0","extract-zip":"^1.6.6","node-ssh":"^6.0.0","os-utils":"0.0.14","dayjs":"^1.11.1","vue":"^3.2.37","jsrsasign":"^10.8.6"},"version":"1.0.8"}
|