>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
15 | l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
16 | (function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
17 | _doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
18 | f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
19 | m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
20 | E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
21 | 4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
22 | (function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
28 | this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
29 | 1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
30 | decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
31 | b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
32 | (function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
33 | 16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
34 | 8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
35 | d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
36 |
37 | module.exports = CryptoJS;
--------------------------------------------------------------------------------
/lib/utils/error-message.js:
--------------------------------------------------------------------------------
1 | const e = {
2 | ItemNotExist({ path }) {
3 | return `文件(夹)${path || '?'}不存在`;
4 | },
5 | Unauthorized({ field, type }) {
6 | let s = '';
7 | if (type === 'empty') {
8 | s = '为空,请输入后重试';
9 | } else if (type === 'invalid') {
10 | s = '已过期或不合法,请重新认证';
11 | } else if (type === 'wrong') {
12 | s = '有误,请重新输入';
13 | }
14 | return `字段${field}${s}`;
15 | },
16 | CommandNotAllowed({ command }) {
17 | return `暂不支持${command}命令`;
18 | },
19 | DriveNotExist({ path }) {
20 | return `路径${path}下未配置云盘`;
21 | },
22 | ModuleNotExist({ module }) {
23 | return `模块${module}不存在`;
24 | },
25 | InvalidPage({ page }) {
26 | return `分页参数${page}不合法`;
27 | },
28 | ItemIsFile({ path }) {
29 | return `路径${path || '?'}对应一个文件,请注意path格式`;
30 | },
31 | ConfigError({ fields }) {
32 | return `参数配置有误,请注意一下这些参数[${fields.toString()}]`;
33 | },
34 | ModuleError(msg) {
35 | return `模块内部错误: ${msg || '???'}`;
36 | },
37 | ReadError({ msg }) {
38 | return `配置读取失败: ${msg}`;
39 | },
40 | SaveError({ msg }) {
41 | return `配置保存失败: ${msg}`;
42 | },
43 | default(type) {
44 | return `发生错误${type || '?'}`;
45 | },
46 | };
47 |
48 | module.exports.parseErrorMsg = function (type, data) {
49 | return e[type] ? e[type](data) : e.default(type);
50 | };
51 |
--------------------------------------------------------------------------------
/lib/utils/fetchAdapter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // https://github.com/sgammon/axios/blob/feature/fetch/lib/adapters/fetch.js
4 |
5 | const settle = require('axios/lib/core/settle');
6 | const buildURL = require('axios/lib/helpers/buildURL');
7 | const buildFullPath = require('axios/lib/core/buildFullPath');
8 | const createError = require('axios/lib/core/createError');
9 |
10 | module.exports = function fetchAdapter(config) {
11 | return new Promise(function dispatchXhrRequest(resolve, reject) {
12 | const requestData = config.data;
13 | const requestHeaders = config.headers;
14 |
15 | // HTTP basic authentication
16 | if (config.auth) {
17 | const username = config.auth.username || '';
18 | const password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
19 | requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
20 | }
21 |
22 | const fullPath = buildFullPath(config.baseURL, config.url);
23 | const request = new Request(buildURL(fullPath, config.params, config.paramsSerializer));
24 |
25 | // copy headers in
26 | const headers = new Headers();
27 | for (const key in requestHeaders) {
28 | if (requestHeaders.hasOwnProperty(key)) {
29 | headers.append(key, requestHeaders[key]);
30 | }
31 | }
32 |
33 | const abort = { state: false, schedule: null };
34 |
35 | if (config.timeout) {
36 | let timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';
37 | if (config.timeoutErrorMessage) {
38 | timeoutErrorMessage = config.timeoutErrorMessage;
39 | }
40 |
41 | abort.schedule = setTimeout(function popTimeout() {
42 | abort.state = true;
43 | reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', config, null));
44 | }, config.timeout);
45 | }
46 |
47 | const fetcher = fetch(request, {
48 | method: config.method.toUpperCase(),
49 | headers: headers,
50 | body: requestData,
51 | redirect: config.maxRedirects ? 'follow' : 'manual',
52 | });
53 |
54 | fetcher.then(
55 | function fetchFollowup(response) {
56 | if (abort.state) {
57 | return;
58 | }
59 | if (abort.schedule) {
60 | clearTimeout(abort.schedule);
61 | }
62 |
63 | // Prepare the response
64 | const responseHeaders = response.headers;
65 | let responseData = null;
66 | switch (config.responseType) {
67 | case 'text':
68 | responseData = response.text();
69 | break;
70 | case 'json':
71 | responseData = response.json();
72 | break;
73 | case 'blob':
74 | responseData = response.blob();
75 | break;
76 | default:
77 | responseData = response.text();
78 | break;
79 | }
80 |
81 | // consume response
82 | if (!responseData) {
83 | reject(createError('Failed to resolve response stream.', config, 'STREAM_FAILED', request, response));
84 | } else {
85 | responseData.then(
86 | function handleResponseData(data) {
87 | const axiosResponse = {
88 | data: data,
89 | status: response.status,
90 | statusText: response.statusText,
91 | headers: responseHeaders,
92 | config: config,
93 | request: request,
94 | requestHeaders: requestHeaders,
95 | };
96 |
97 | // we're good to go
98 | settle(resolve, reject, axiosResponse);
99 | },
100 | function handleDataError(dataErr) {
101 | reject(dataErr || createError('Stream decode error', config, response.statusText, request, response));
102 | }
103 | );
104 | }
105 | },
106 | function handleFetchError(err) {
107 | if (abort.state) {
108 | return;
109 | }
110 | if (abort.schedule) {
111 | clearTimeout(abort.schedule);
112 | }
113 | if (err instanceof Error) {
114 | reject(err);
115 | } else {
116 | reject(createError('Network Error', config, null, request, err));
117 | }
118 | }
119 | );
120 | });
121 | };
122 |
--------------------------------------------------------------------------------
/lib/utils/logger.js:
--------------------------------------------------------------------------------
1 | module.exports = console;
2 |
--------------------------------------------------------------------------------
/lib/utils/mime.js:
--------------------------------------------------------------------------------
1 | const m = {
2 | 'application/andrew-inset': ['ez'],
3 | 'application/applixware': ['aw'],
4 | 'application/atom+xml': ['atom'],
5 | 'application/atomcat+xml': ['atomcat'],
6 | 'application/atomdeleted+xml': ['atomdeleted'],
7 | 'application/atomsvc+xml': ['atomsvc'],
8 | 'application/atsc-dwd+xml': ['dwd'],
9 | 'application/atsc-held+xml': ['held'],
10 | 'application/atsc-rsat+xml': ['rsat'],
11 | 'application/bdoc': ['bdoc'],
12 | 'application/calendar+xml': ['xcs'],
13 | 'application/ccxml+xml': ['ccxml'],
14 | 'application/cdfx+xml': ['cdfx'],
15 | 'application/cdmi-capability': ['cdmia'],
16 | 'application/cdmi-container': ['cdmic'],
17 | 'application/cdmi-domain': ['cdmid'],
18 | 'application/cdmi-object': ['cdmio'],
19 | 'application/cdmi-queue': ['cdmiq'],
20 | 'application/cu-seeme': ['cu'],
21 | 'application/dash+xml': ['mpd'],
22 | 'application/davmount+xml': ['davmount'],
23 | 'application/docbook+xml': ['dbk'],
24 | 'application/dssc+der': ['dssc'],
25 | 'application/dssc+xml': ['xdssc'],
26 | 'application/ecmascript': ['ecma', 'es'],
27 | 'application/emma+xml': ['emma'],
28 | 'application/emotionml+xml': ['emotionml'],
29 | 'application/epub+zip': ['epub'],
30 | 'application/exi': ['exi'],
31 | 'application/fdt+xml': ['fdt'],
32 | 'application/font-tdpfr': ['pfr'],
33 | 'application/geo+json': ['geojson'],
34 | 'application/gml+xml': ['gml'],
35 | 'application/gpx+xml': ['gpx'],
36 | 'application/gxf': ['gxf'],
37 | 'application/gzip': ['gz'],
38 | 'application/hjson': ['hjson'],
39 | 'application/hyperstudio': ['stk'],
40 | 'application/inkml+xml': ['ink', 'inkml'],
41 | 'application/ipfix': ['ipfix'],
42 | 'application/its+xml': ['its'],
43 | 'application/java-archive': ['jar', 'war', 'ear'],
44 | 'application/java-serialized-object': ['ser'],
45 | 'application/java-vm': ['class'],
46 | 'application/javascript': ['js', 'mjs'],
47 | 'application/json': ['json', 'map'],
48 | 'application/json5': ['json5'],
49 | 'application/jsonml+json': ['jsonml'],
50 | 'application/ld+json': ['jsonld'],
51 | 'application/lgr+xml': ['lgr'],
52 | 'application/lost+xml': ['lostxml'],
53 | 'application/mac-binhex40': ['hqx'],
54 | 'application/mac-compactpro': ['cpt'],
55 | 'application/mads+xml': ['mads'],
56 | 'application/manifest+json': ['webmanifest'],
57 | 'application/marc': ['mrc'],
58 | 'application/marcxml+xml': ['mrcx'],
59 | 'application/mathematica': ['ma', 'nb', 'mb'],
60 | 'application/mathml+xml': ['mathml'],
61 | 'application/mbox': ['mbox'],
62 | 'application/mediaservercontrol+xml': ['mscml'],
63 | 'application/metalink+xml': ['metalink'],
64 | 'application/metalink4+xml': ['meta4'],
65 | 'application/mets+xml': ['mets'],
66 | 'application/mmt-aei+xml': ['maei'],
67 | 'application/mmt-usd+xml': ['musd'],
68 | 'application/mods+xml': ['mods'],
69 | 'application/mp21': ['m21', 'mp21'],
70 | 'application/mp4': ['mp4s', 'm4p'],
71 | 'application/mrb-consumer+xml': ['*xdf'],
72 | 'application/mrb-publish+xml': ['*xdf'],
73 | 'application/msword': ['doc', 'dot'],
74 | 'application/mxf': ['mxf'],
75 | 'application/n-quads': ['nq'],
76 | 'application/n-triples': ['nt'],
77 | 'application/node': ['cjs'],
78 | 'application/octet-stream': ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy', 'exe', 'dll', 'deb', 'dmg', 'iso', 'img', 'msi', 'msp', 'msm', 'buffer'],
79 | 'application/oda': ['oda'],
80 | 'application/oebps-package+xml': ['opf'],
81 | 'application/ogg': ['ogx'],
82 | 'application/omdoc+xml': ['omdoc'],
83 | 'application/onenote': ['onetoc', 'onetoc2', 'onetmp', 'onepkg'],
84 | 'application/oxps': ['oxps'],
85 | 'application/p2p-overlay+xml': ['relo'],
86 | 'application/patch-ops-error+xml': ['*xer'],
87 | 'application/pdf': ['pdf'],
88 | 'application/pgp-encrypted': ['pgp'],
89 | 'application/pgp-signature': ['asc', 'sig'],
90 | 'application/pics-rules': ['prf'],
91 | 'application/pkcs10': ['p10'],
92 | 'application/pkcs7-mime': ['p7m', 'p7c'],
93 | 'application/pkcs7-signature': ['p7s'],
94 | 'application/pkcs8': ['p8'],
95 | 'application/pkix-attr-cert': ['ac'],
96 | 'application/pkix-cert': ['cer'],
97 | 'application/pkix-crl': ['crl'],
98 | 'application/pkix-pkipath': ['pkipath'],
99 | 'application/pkixcmp': ['pki'],
100 | 'application/pls+xml': ['pls'],
101 | 'application/postscript': ['ai', 'eps', 'ps'],
102 | 'application/provenance+xml': ['provx'],
103 | 'application/pskc+xml': ['pskcxml'],
104 | 'application/raml+yaml': ['raml'],
105 | 'application/rdf+xml': ['rdf', 'owl'],
106 | 'application/reginfo+xml': ['rif'],
107 | 'application/relax-ng-compact-syntax': ['rnc'],
108 | 'application/resource-lists+xml': ['rl'],
109 | 'application/resource-lists-diff+xml': ['rld'],
110 | 'application/rls-services+xml': ['rs'],
111 | 'application/route-apd+xml': ['rapd'],
112 | 'application/route-s-tsid+xml': ['sls'],
113 | 'application/route-usd+xml': ['rusd'],
114 | 'application/rpki-ghostbusters': ['gbr'],
115 | 'application/rpki-manifest': ['mft'],
116 | 'application/rpki-roa': ['roa'],
117 | 'application/rsd+xml': ['rsd'],
118 | 'application/rss+xml': ['rss'],
119 | 'application/rtf': ['rtf'],
120 | 'application/sbml+xml': ['sbml'],
121 | 'application/scvp-cv-request': ['scq'],
122 | 'application/scvp-cv-response': ['scs'],
123 | 'application/scvp-vp-request': ['spq'],
124 | 'application/scvp-vp-response': ['spp'],
125 | 'application/sdp': ['sdp'],
126 | 'application/senml+xml': ['senmlx'],
127 | 'application/sensml+xml': ['sensmlx'],
128 | 'application/set-payment-initiation': ['setpay'],
129 | 'application/set-registration-initiation': ['setreg'],
130 | 'application/shf+xml': ['shf'],
131 | 'application/sieve': ['siv', 'sieve'],
132 | 'application/smil+xml': ['smi', 'smil'],
133 | 'application/sparql-query': ['rq'],
134 | 'application/sparql-results+xml': ['srx'],
135 | 'application/srgs': ['gram'],
136 | 'application/srgs+xml': ['grxml'],
137 | 'application/sru+xml': ['sru'],
138 | 'application/ssdl+xml': ['ssdl'],
139 | 'application/ssml+xml': ['ssml'],
140 | 'application/swid+xml': ['swidtag'],
141 | 'application/tei+xml': ['tei', 'teicorpus'],
142 | 'application/thraud+xml': ['tfi'],
143 | 'application/timestamped-data': ['tsd'],
144 | 'application/toml': ['toml'],
145 | 'application/ttml+xml': ['ttml'],
146 | 'application/urc-ressheet+xml': ['rsheet'],
147 | 'application/voicexml+xml': ['vxml'],
148 | 'application/wasm': ['wasm'],
149 | 'application/widget': ['wgt'],
150 | 'application/winhlp': ['hlp'],
151 | 'application/wsdl+xml': ['wsdl'],
152 | 'application/wspolicy+xml': ['wspolicy'],
153 | 'application/xaml+xml': ['xaml'],
154 | 'application/xcap-att+xml': ['xav'],
155 | 'application/xcap-caps+xml': ['xca'],
156 | 'application/xcap-diff+xml': ['xdf'],
157 | 'application/xcap-el+xml': ['xel'],
158 | 'application/xcap-error+xml': ['xer'],
159 | 'application/xcap-ns+xml': ['xns'],
160 | 'application/xenc+xml': ['xenc'],
161 | 'application/xhtml+xml': ['xhtml', 'xht'],
162 | 'application/xliff+xml': ['xlf'],
163 | 'application/xml': ['xml', 'xsl', 'xsd', 'rng'],
164 | 'application/xml-dtd': ['dtd'],
165 | 'application/xop+xml': ['xop'],
166 | 'application/xproc+xml': ['xpl'],
167 | 'application/xslt+xml': ['xslt'],
168 | 'application/xspf+xml': ['xspf'],
169 | 'application/xv+xml': ['mxml', 'xhvml', 'xvml', 'xvm'],
170 | 'application/yang': ['yang'],
171 | 'application/yin+xml': ['yin'],
172 | 'application/zip': ['zip'],
173 | 'audio/3gpp': ['*3gpp'],
174 | 'audio/adpcm': ['adp'],
175 | 'audio/basic': ['au', 'snd'],
176 | 'audio/midi': ['mid', 'midi', 'kar', 'rmi'],
177 | 'audio/mobile-xmf': ['mxmf'],
178 | 'audio/mp3': ['*mp3'],
179 | 'audio/mp4': ['m4a', 'mp4a'],
180 | 'audio/mpeg': ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'],
181 | 'audio/ogg': ['oga', 'ogg', 'spx'],
182 | 'audio/s3m': ['s3m'],
183 | 'audio/silk': ['sil'],
184 | 'audio/wav': ['wav'],
185 | 'audio/wave': ['*wav'],
186 | 'audio/webm': ['weba'],
187 | 'audio/xm': ['xm'],
188 | 'font/collection': ['ttc'],
189 | 'font/otf': ['otf'],
190 | 'font/ttf': ['ttf'],
191 | 'font/woff': ['woff'],
192 | 'font/woff2': ['woff2'],
193 | 'image/aces': ['exr'],
194 | 'image/apng': ['apng'],
195 | 'image/bmp': ['bmp'],
196 | 'image/cgm': ['cgm'],
197 | 'image/dicom-rle': ['drle'],
198 | 'image/emf': ['emf'],
199 | 'image/fits': ['fits'],
200 | 'image/g3fax': ['g3'],
201 | 'image/gif': ['gif'],
202 | 'image/heic': ['heic'],
203 | 'image/heic-sequence': ['heics'],
204 | 'image/heif': ['heif'],
205 | 'image/heif-sequence': ['heifs'],
206 | 'image/hej2k': ['hej2'],
207 | 'image/hsj2': ['hsj2'],
208 | 'image/ief': ['ief'],
209 | 'image/jls': ['jls'],
210 | 'image/jp2': ['jp2', 'jpg2'],
211 | 'image/jpeg': ['jpeg', 'jpg', 'jpe'],
212 | 'image/jph': ['jph'],
213 | 'image/jphc': ['jhc'],
214 | 'image/jpm': ['jpm'],
215 | 'image/jpx': ['jpx', 'jpf'],
216 | 'image/jxr': ['jxr'],
217 | 'image/jxra': ['jxra'],
218 | 'image/jxrs': ['jxrs'],
219 | 'image/jxs': ['jxs'],
220 | 'image/jxsc': ['jxsc'],
221 | 'image/jxsi': ['jxsi'],
222 | 'image/jxss': ['jxss'],
223 | 'image/ktx': ['ktx'],
224 | 'image/png': ['png'],
225 | 'image/sgi': ['sgi'],
226 | 'image/svg+xml': ['svg', 'svgz'],
227 | 'image/t38': ['t38'],
228 | 'image/tiff': ['tif', 'tiff'],
229 | 'image/tiff-fx': ['tfx'],
230 | 'image/webp': ['webp'],
231 | 'image/wmf': ['wmf'],
232 | 'message/disposition-notification': ['disposition-notification'],
233 | 'message/global': ['u8msg'],
234 | 'message/global-delivery-status': ['u8dsn'],
235 | 'message/global-disposition-notification': ['u8mdn'],
236 | 'message/global-headers': ['u8hdr'],
237 | 'message/rfc822': ['eml', 'mime'],
238 | 'model/3mf': ['3mf'],
239 | 'model/gltf+json': ['gltf'],
240 | 'model/gltf-binary': ['glb'],
241 | 'model/iges': ['igs', 'iges'],
242 | 'model/mesh': ['msh', 'mesh', 'silo'],
243 | 'model/mtl': ['mtl'],
244 | 'model/obj': ['obj'],
245 | 'model/stl': ['stl'],
246 | 'model/vrml': ['wrl', 'vrml'],
247 | 'model/x3d+binary': ['*x3db', 'x3dbz'],
248 | 'model/x3d+fastinfoset': ['x3db'],
249 | 'model/x3d+vrml': ['*x3dv', 'x3dvz'],
250 | 'model/x3d+xml': ['x3d', 'x3dz'],
251 | 'model/x3d-vrml': ['x3dv'],
252 | 'text/cache-manifest': ['appcache', 'manifest'],
253 | 'text/calendar': ['ics', 'ifb'],
254 | 'text/coffeescript': ['coffee', 'litcoffee'],
255 | 'text/css': ['css'],
256 | 'text/csv': ['csv'],
257 | 'text/html': ['html', 'htm', 'shtml'],
258 | 'text/jade': ['jade'],
259 | 'text/jsx': ['jsx'],
260 | 'text/less': ['less'],
261 | 'text/markdown': ['markdown', 'md'],
262 | 'text/mathml': ['mml'],
263 | 'text/mdx': ['mdx'],
264 | 'text/n3': ['n3'],
265 | 'text/plain': ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini'],
266 | 'text/richtext': ['rtx'],
267 | 'text/rtf': ['*rtf'],
268 | 'text/sgml': ['sgml', 'sgm'],
269 | 'text/shex': ['shex'],
270 | 'text/slim': ['slim', 'slm'],
271 | 'text/stylus': ['stylus', 'styl'],
272 | 'text/tab-separated-values': ['tsv'],
273 | 'text/troff': ['t', 'tr', 'roff', 'man', 'me', 'ms'],
274 | 'text/turtle': ['ttl'],
275 | 'text/uri-list': ['uri', 'uris', 'urls'],
276 | 'text/vcard': ['vcard'],
277 | 'text/vtt': ['vtt'],
278 | 'text/xml': ['*xml'],
279 | 'text/yaml': ['yaml', 'yml'],
280 | 'video/3gpp': ['3gp', '3gpp'],
281 | 'video/3gpp2': ['3g2'],
282 | 'video/h261': ['h261'],
283 | 'video/h263': ['h263'],
284 | 'video/h264': ['h264'],
285 | 'video/jpeg': ['jpgv'],
286 | 'video/jpm': ['*jpm', 'jpgm'],
287 | 'video/mj2': ['mj2', 'mjp2'],
288 | 'video/mp2t': ['ts'],
289 | 'video/mp4': ['mp4', 'mp4v', 'mpg4'],
290 | 'video/mpeg': ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'],
291 | 'video/ogg': ['ogv'],
292 | 'video/quicktime': ['qt', 'mov'],
293 | 'video/webm': ['webm'],
294 | };
295 |
296 | const map = {};
297 | Object.keys(m).forEach((t) => {
298 | m[t].forEach((e) => {
299 | map[e] = t;
300 | });
301 | });
302 |
303 | map.mkv = 'video/x-matroska';
304 | map.flv = 'video/x-flv';
305 | map.m3u8 = 'application/x-mpegURL';
306 |
307 | module.exports = map;
308 |
--------------------------------------------------------------------------------
/lib/utils/node.js:
--------------------------------------------------------------------------------
1 | exports.query2Obj = function (s = '', o = {}) {
2 | for (const [k, v] of new URLSearchParams(s)) {
3 | o[k] = v;
4 | }
5 | return o;
6 | };
7 |
8 | exports.cookie2Str = function (n, v, o = {}) {
9 | let s = encodeURIComponent(n) + '=' + encodeURIComponent(v);
10 | const { maxAge, domain, path, expires, httpOnly, secure, sameSite } = o;
11 | s += typeof maxAge === 'number' ? '; Max-Age=' + maxAge : '';
12 | domain ? (s += '; Domain=' + domain) : '';
13 | path ? (s += '; Path=' + path) : '';
14 | expires ? (s += '; Expires=' + expires) : '';
15 | httpOnly ? (s += '; HttpOnly') : '';
16 | secure ? (s += '; Secure') : '';
17 | sameSite ? (s += '; SameSite=' + sameSite) : '';
18 | return s;
19 | };
20 |
21 | exports._sha1 = require('./tiny-sha1');
22 |
23 | exports.path = {
24 | basename: (s) => (s ? s.slice(s.lastIndexOf('/') + 1) : ''),
25 | extname: (s) => (s ? s.slice(s.lastIndexOf('.') + 1) : ''),
26 | };
27 |
28 | const request = (exports.request = require('./tiny-request'));
29 | request.defaults.timeout = 5000;
30 |
31 | exports.exposeHeadersWhenProxy = function (k) {
32 | if (typeof k !== 'string') {
33 | return false;
34 | }
35 | k = k.toLowerCase();
36 | if (k.startsWith('content-')) {
37 | return k;
38 | }
39 | return ['accept-ranges', 'date'].includes(k);
40 | };
41 |
42 | const mime = require('./mime.js');
43 | exports.mime = {
44 | get: (path) => mime[path.slice(path.lastIndexOf('.') + 1)] || 'application/vnd.op-unknown',
45 | };
46 |
47 | const NUM_CHARS = {};
48 | '0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'.split('').forEach((v, i) => {
49 | NUM_CHARS[i] = v;
50 | NUM_CHARS[v] = i;
51 | });
52 |
53 | exports.NumberUtil = {
54 | parse62: (s) => {
55 | let num = 0,
56 | base = 1;
57 | s.split('')
58 | .reverse()
59 | .forEach((c) => {
60 | num += NUM_CHARS[c] * base;
61 | base *= 62;
62 | });
63 | return num;
64 | },
65 | to62: (n) => {
66 | const arr = [];
67 | while (n > 0) {
68 | arr.push(NUM_CHARS[n % 62]);
69 | n = Math.floor(n / 62);
70 | }
71 | if (arr.length === 0) {
72 | return '0';
73 | }
74 | return arr.reverse().join('');
75 | },
76 | };
77 |
78 | const { parseErrorMsg } = require('./error-message');
79 |
80 | class RTError extends Error {
81 | constructor(status, type, data) {
82 | super(parseErrorMsg(type, data || {}));
83 | this.status = status;
84 | this.type = type;
85 | this.data = data || {};
86 | this.expose = true;
87 | }
88 | }
89 |
90 | exports.RTError = RTError;
91 |
92 | const logger = require('./logger');
93 |
94 | class IDHelper {
95 | constructor(root) {
96 | this.root = root;
97 | this.icache = {};
98 | this.etime = Date.now() + 3600 * 1000;
99 | }
100 |
101 | get isValid() {
102 | return Date.now() < this.etime;
103 | }
104 |
105 | async findChildItem(pid, name) {
106 | return Promise.reject(new RTError(500, 'unsupported method: findChildItem(' + pid + ',' + name + ')'));
107 | }
108 |
109 | async getIDByPath(path = '/') {
110 | return this.getItemByPath(path).then((e) => e.id);
111 | }
112 |
113 | async getItemByPath(path) {
114 | return this._getItemByPath(
115 | path.split('/').filter((e) => e),
116 | { type: 1, id: this.root }
117 | );
118 | }
119 |
120 | async _getItemByPath(paths, item) {
121 | if (paths.length === 0) {
122 | return item;
123 | }
124 | const pid = item.id;
125 | const cache = this.icache[pid] || {};
126 | const name = paths.shift();
127 | if (!cache[name] || cache[name].etime < Date.now()) {
128 | logger.info('pid:' + pid + ' ' + name);
129 | const cItem = await this.findChildItem(pid, name);
130 | if (!cItem) {
131 | throw new RTError(404, 'ItemNotExist');
132 | }
133 | cItem.etime = Date.now() + 300000;
134 | cache[name] = cItem;
135 | // 保证path中出现的都是文件夹
136 | if (cItem.type !== 1 && paths.length > 0) {
137 | throw new RTError(404, 'ItemNotExist');
138 | }
139 | }
140 | this.icache[pid] = cache;
141 | return this._getItemByPath(paths, cache[name]);
142 | }
143 | }
144 |
145 | exports.IDHelper = IDHelper;
146 |
147 | exports.P = exports._P = (name, value, desc, level, meta, textarea, star) => {
148 | const r = { name, value, desc, level };
149 | if (Array.isArray(meta)) {
150 | r.select = meta;
151 | } else {
152 | r.placeholder = meta;
153 | if (textarea) {
154 | r.textarea = true;
155 | }
156 | }
157 | if (star) {
158 | r.star = true;
159 | }
160 | if (meta.hidden) {
161 | r.hidden = true;
162 | }
163 | return r;
164 | };
165 |
166 | exports.beautifyObject = function beautifyObject(ob) {
167 | if (Array.isArray(ob)) {
168 | return ob.map((e) => beautifyObject(e));
169 | }
170 | if (typeof ob === 'string' || typeof ob === 'number' || typeof ob === 'boolean') {
171 | return ob;
172 | }
173 | const nob = {};
174 | Object.keys(ob)
175 | .sort()
176 | .forEach((k) => {
177 | nob[k] = typeof ob[k] === 'object' ? beautifyObject(ob[k]) : ob[k];
178 | });
179 | return nob;
180 | };
181 |
182 | exports.deleteAttributes = function (obj, arr) {
183 | arr.forEach((e) => delete obj[e]);
184 | };
185 |
--------------------------------------------------------------------------------
/lib/utils/simple-router.js:
--------------------------------------------------------------------------------
1 | const SimpleRouter = function () {
2 | this.routers = {
3 | GET: {},
4 | POST: {},
5 | DELETE: {},
6 | prefix: [],
7 | regex: [],
8 | default: () => {},
9 | };
10 | };
11 | SimpleRouter.prototype.add = function (m, p, f) {
12 | if (Array.isArray(m)) {
13 | m.forEach((e) => {
14 | this.routers[e][p] = f;
15 | });
16 | }
17 | if (typeof m === 'string') {
18 | this.routers[m][p] = f;
19 | }
20 | };
21 |
22 | SimpleRouter.prototype.get = function (p, f) {
23 | this.routers.GET[p] = f;
24 | };
25 | SimpleRouter.prototype.post = function (p, f) {
26 | this.routers.POST[p] = f;
27 | };
28 | SimpleRouter.prototype.delete = function (p, f) {
29 | this.routers.DELETE[p] = f;
30 | };
31 | SimpleRouter.prototype.setDefault = function (f) {
32 | this.routers.default = f;
33 | };
34 | SimpleRouter.prototype.regex = function (p, f) {
35 | this.routers.regex.push({ p, f });
36 | };
37 | SimpleRouter.prototype.prefix = function (p, f) {
38 | this.routers.prefix.push({ p, f });
39 | };
40 | SimpleRouter.prototype.handle = async function (ctx, next, path) {
41 | const m = ctx.request.method;
42 | if (this.routers[m] && this.routers[m][path]) {
43 | return this.routers[m][path](ctx);
44 | }
45 | const item = this.routers.regex.find(({ p }) => p.test(path));
46 | if (item) {
47 | return item.f(ctx, next, path);
48 | }
49 |
50 | const item1 = this.routers.prefix.find(({ p }) => path.startsWith(p));
51 | if (item1) {
52 | return item1.f(ctx, next, path.slice(item1.p.length));
53 | }
54 | return this.routers.default(ctx, next, path);
55 | };
56 |
57 | module.exports = SimpleRouter;
58 |
--------------------------------------------------------------------------------
/lib/utils/tiny-request/browser-fetch.js:
--------------------------------------------------------------------------------
1 | function request({ method, url, headers, body }, config) {
2 | return new Promise((resolve, reject) => {
3 | const abort = { state: false, schedule: null };
4 |
5 | if (config.timeout) {
6 | abort.schedule = setTimeout(() => {
7 | abort.state = true;
8 | reject(new Error('timeout of ' + config.timeout + 'ms exceeded'));
9 | }, config.timeout);
10 | }
11 | fetch(url, {
12 | method,
13 | headers: new Headers(headers),
14 | body,
15 | redirect: 'manual',
16 | })
17 | .then((res) => {
18 | if (abort.state) {
19 | return;
20 | }
21 | if (abort.schedule) {
22 | clearTimeout(abort.schedule);
23 | }
24 |
25 | const h = {};
26 | for (const [k, v] of res.headers) {
27 | h[k] = v;
28 | }
29 | if (h['set-cookie']) {
30 | // set-cookie is special
31 | h['set-cookie'] = h['set-cookie'].split(/(? e.trim());
32 | }
33 |
34 | const response = {
35 | status: res.status,
36 | headers: h,
37 | data: '',
38 | };
39 |
40 | if (config.responseType === 'stream') {
41 | response.data = res.body;
42 | return resolve(response);
43 | }
44 |
45 | if ((response.status >= 300 && response.status < 400) || response.status === 204 || method === 'HEAD') {
46 | return resolve(response);
47 | }
48 |
49 | // just delete
50 | if (['gzip', 'compress', 'deflate'].includes(response.headers['content-encoding'])) {
51 | delete response.headers['content-encoding'];
52 | }
53 |
54 | let responseData = res;
55 | switch (config.responseType) {
56 | case 'arraybuffer':
57 | responseData = responseData.arrayBuffer();
58 | break;
59 | case 'blob':
60 | responseData = responseData.blob();
61 | break;
62 | default:
63 | responseData = responseData.text();
64 | }
65 |
66 | // consume response
67 | if (!responseData) {
68 | reject(new Error('Failed to resolve response stream.'));
69 | } else {
70 | responseData.then(
71 | (data) => {
72 | response.data = data;
73 | resolve(response);
74 | },
75 | (dataErr) => {
76 | reject(dataErr || new Error('Stream decode error'));
77 | }
78 | );
79 | }
80 | })
81 | .catch((err) => {
82 | if (abort.state) {
83 | return;
84 | }
85 | if (abort.schedule) {
86 | clearTimeout(abort.schedule);
87 | }
88 | if (err instanceof Error) {
89 | reject(err);
90 | } else {
91 | reject(new Error('Network Error'));
92 | }
93 | });
94 | });
95 | }
96 |
97 | module.exports = request;
98 |
--------------------------------------------------------------------------------
/lib/utils/tiny-request/index.d.ts:
--------------------------------------------------------------------------------
1 | export interface RequestAdapter {
2 | (config: RequestRequestConfig): Promise;
3 | }
4 |
5 | export interface RequestResponseAdapter {
6 | (res: RequestResponse): Promise;
7 | }
8 |
9 | export interface RequestProxyConfig {
10 | host: string;
11 | port: number;
12 | }
13 |
14 | export type Method =
15 | | 'get' | 'GET'
16 | | 'delete' | 'DELETE'
17 | | 'head' | 'HEAD'
18 | | 'options' | 'OPTIONS'
19 | | 'post' | 'POST'
20 | | 'put' | 'PUT'
21 | | 'patch' | 'PATCH'
22 | | 'purge' | 'PURGE'
23 | | 'link' | 'LINK'
24 | | 'unlink' | 'UNLINK'
25 |
26 | export type ResponseType =
27 | | 'arraybuffer'
28 | | 'blob'
29 | | 'document'
30 | | 'json'
31 | | 'text'
32 | | 'stream'
33 |
34 | export interface RequestRequestConfig {
35 | url?: string;
36 | params?: any;
37 | method?: Method;
38 | baseURL?: string;
39 | headers?: any;
40 | body?:any;
41 | data?: any;
42 | timeout?: number;
43 | adapter?: RequestAdapter;
44 | responseType?: ResponseType;
45 | proxy?: RequestProxyConfig;
46 | onResponse?: RequestResponseAdapter;
47 | }
48 |
49 | export interface RequestRequest {
50 | method: Method;
51 | url: string;
52 | headers: any;
53 | body: string | any;
54 | }
55 |
56 | export interface RequestResponse {
57 | status: number;
58 | headers: any;
59 | data: T;
60 | config?: RequestRequestConfig;
61 | request?: RequestRequest;
62 | }
63 |
64 | export interface RequestInstance {
65 | defaults: RequestRequestConfig;
66 |
67 | request | any>(config: RequestRequestConfig): Promise;
68 |
69 | get | any>(url: string, config?: RequestRequestConfig): Promise;
70 |
71 | delete | any>(url: string, config?: RequestRequestConfig): Promise;
72 |
73 | head | any>(url: string, config?: RequestRequestConfig): Promise;
74 |
75 | options | any>(url: string, config?: RequestRequestConfig): Promise;
76 |
77 | post | any>(url: string, data?: any, config?: RequestRequestConfig): Promise;
78 |
79 | put | any>(url: string, data?: any, config?: RequestRequestConfig): Promise;
80 |
81 | patch | any>(url: string, data?: any, config?: RequestRequestConfig): Promise;
82 |
83 | onResponse(f: RequestResponseAdapter): Promise;
84 | }
85 |
86 | export interface RequestStatic extends RequestInstance {
87 | create(config?: RequestRequestConfig): RequestInstance;
88 | }
89 |
90 | declare const request: RequestStatic;
91 |
92 | export default request;
93 |
--------------------------------------------------------------------------------
/lib/utils/tiny-request/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 很純粹的http请求工具
3 | *
4 | * 不支持重定向,需要手动处理
5 | *
6 | * method 需要大写
7 | * url 可以包含中文字符
8 | * headers 字段大写格式
9 | * responseType 支持 json text
10 | *
11 | * 支持默认baseURL, headers
12 | */
13 |
14 | function setIfUndefined(o, a, v) {
15 | o[a] === undefined ? (o[a] = v) : '';
16 | }
17 |
18 | const adapters = {};
19 | adapters.n = require('./node-http');
20 | adapters.f = require('./browser-fetch');
21 |
22 | function getDefaultAdapter() {
23 | return adapters[typeof fetch === 'function' ? 'f' : 'n'];
24 | }
25 |
26 | function mergeConfig(config1, config2) {
27 | return Object.assign({}, config1, config2, { headers: Object.assign({}, config1.headers, config2.headers) });
28 | }
29 |
30 | function buildFullURL(url, baseURL, params) {
31 | const u = new URL(url, baseURL || 'http://example.com');
32 | if (!['http:', 'https:'].includes(u.protocol)) {
33 | // url中包含了 :
34 | if (url[0] === '/') {
35 | u.href = baseURL;
36 | u.pathname = url;
37 | } else {
38 | u.href = baseURL + url;
39 | }
40 | }
41 |
42 | if (params) {
43 | const _searchParams = u.searchParams;
44 | Object.entries(params).forEach(([k, v]) => _searchParams.set(k, v.toString()));
45 | }
46 |
47 | return u.href;
48 | }
49 |
50 | const defaults = {
51 | baseURL: '',
52 | headers: {},
53 | responseType: 'json',
54 | adapter: getDefaultAdapter(),
55 | onResponse: (d) => d,
56 | };
57 |
58 | class Request {
59 | constructor(config) {
60 | this.defaults = config;
61 | }
62 |
63 | async request(config) {
64 | config = mergeConfig(this.defaults, config);
65 |
66 | const { url, method, headers, body, data, baseURL, params } = config;
67 | const req = { method: (method || 'GET').toUpperCase(), headers };
68 |
69 | req.url = buildFullURL(url, baseURL, params);
70 |
71 | setIfUndefined(headers, 'User-Agent', 'tiny-request/0.0');
72 | setIfUndefined(headers, 'Accept', 'application/json, text/plain, */*');
73 |
74 | if (['GET', 'HEAD'].includes(req.method)) {
75 | req.body = null;
76 | } else if (body) {
77 | req.body = body;
78 | } else if (data instanceof URLSearchParams) {
79 | setIfUndefined(headers, 'Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
80 | req.body = data.toString();
81 | } else if (data && typeof data === 'object') {
82 | setIfUndefined(headers, 'Content-Type', 'application/json;charset=utf-8');
83 | req.body = JSON.stringify(data);
84 | } else if (typeof data === 'string') {
85 | req.body = data;
86 | } else {
87 | req.body = '';
88 | }
89 |
90 | return config
91 | .adapter(req, config)
92 | .then((res) => {
93 | if (res.data && config.responseType === 'json' && typeof res.data === 'string') {
94 | try {
95 | res.data = JSON.parse(res.data);
96 | } catch (e) {}
97 | }
98 | res.request = req;
99 | res.config = config;
100 | return res;
101 | })
102 | .then(config.onResponse)
103 | .catch((e) => {
104 | e.isHttpError = true;
105 | if (Object.getPrototypeOf(e) === Error.prototype) {
106 | e.message = 'Internal HttpError: ' + e.message;
107 | }
108 | return Promise.reject(e);
109 | });
110 | }
111 |
112 | async reject() {}
113 | }
114 |
115 | // Provide aliases for supported request methods
116 | ['delete', 'get', 'head', 'options'].forEach((m) => {
117 | Request.prototype[m] = function (url, config = {}) {
118 | config.method = m;
119 | config.url = url;
120 | return this.request(config);
121 | };
122 | });
123 |
124 | ['post', 'put', 'patch'].forEach((m) => {
125 | Request.prototype[m] = function (url, data = '', config = {}) {
126 | config.method = m;
127 | config.url = url;
128 | config.data = data;
129 | return this.request(config);
130 | };
131 | });
132 |
133 | // Create the default instance to be exported
134 | const request = new Request(defaults);
135 |
136 | request.Request = Request;
137 |
138 | // Factory for creating new instances
139 | request.create = function create(config) {
140 | return new Request(mergeConfig(this.defaults, config));
141 | };
142 |
143 | module.exports = request;
144 |
145 | // Allow use of default import syntax in TypeScript
146 | module.exports.default = request;
147 |
--------------------------------------------------------------------------------
/lib/utils/tiny-request/node-http.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const https = require('https');
3 | const zlib = require('zlib');
4 |
5 | // utf8解码未处理bom
6 | async function request({ method, url, headers, body }, config) {
7 | const u = new URL(url);
8 | const options = {
9 | hostname: u.hostname,
10 | port: u.port,
11 | path: u.pathname + u.search,
12 | method,
13 | headers,
14 | };
15 |
16 | if (config.proxy) {
17 | options.hostname = config.proxy.host;
18 | options.port = config.proxy.port;
19 | options.path = url;
20 | headers.Host = u.host;
21 | }
22 |
23 | return new Promise((resolve, reject) => {
24 | const transport = u.protocol === 'https:' && !config.proxy ? https : http;
25 |
26 | // Create the request
27 | const req = transport.request(options, function handleResponse(res) {
28 | if (req.aborted) {
29 | return;
30 | }
31 |
32 | const response = {
33 | status: res.statusCode,
34 | headers: res.headers,
35 | data: '',
36 | };
37 | // forward stream, do nothing!
38 | if (config.responseType === 'stream') {
39 | response.data = res;
40 | resolve(response);
41 | return;
42 | }
43 |
44 | // if redirect or no content or HEAD method, do not need body!
45 | if ((response.status >= 300 && response.status < 400) || response.status === 204 || method === 'HEAD') {
46 | resolve(response);
47 | return;
48 | }
49 |
50 | let stream = res;
51 |
52 | if (['gzip', 'compress', 'deflate'].includes(response.headers['content-encoding'])) {
53 | // add the unzipper to the body stream processing pipeline
54 | stream = stream.pipe(zlib.createUnzip());
55 | // remove the content-encoding in order to not confuse downstream operations
56 | delete response.headers['content-encoding'];
57 | }
58 |
59 | const responseBuffer = [];
60 | stream.on('data', function handleStreamData(chunk) {
61 | responseBuffer.push(chunk);
62 | });
63 |
64 | stream.on('error', function handleStreamError(err) {
65 | if (req.aborted) {
66 | return;
67 | }
68 | reject(err);
69 | });
70 |
71 | stream.on('end', function handleStreamEnd() {
72 | let responseData = Buffer.concat(responseBuffer);
73 | if (config.responseType !== 'arraybuffer') {
74 | responseData = responseData.toString('utf8');
75 | }
76 | response.data = responseData;
77 | resolve(response);
78 | });
79 | });
80 |
81 | // Handle errors
82 | req.on('error', function handleRequestError(err) {
83 | if (req.aborted) {
84 | return;
85 | }
86 | reject(err);
87 | });
88 |
89 | // Handle request timeout
90 | if (config.timeout) {
91 | // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
92 | // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
93 | // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
94 | // And then these socket which be hang up will devoring CPU little by little.
95 | // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
96 | req.setTimeout(config.timeout, function handleRequestTimeout() {
97 | req.abort();
98 | reject(new Error('timeout of ' + config.timeout + 'ms exceeded'));
99 | });
100 | }
101 |
102 | // Send the request
103 | req.end(body);
104 | });
105 | }
106 |
107 | module.exports = request;
108 |
--------------------------------------------------------------------------------
/lib/utils/tiny-sha1.js:
--------------------------------------------------------------------------------
1 | // https://github.com/jbt/tiny-hashes/blob/master/sha1/sha1.js
2 | function sha1(b) {
3 | var i,
4 | W = [],
5 | A,
6 | B,
7 | C,
8 | D,
9 | h = [(A = 0x67452301), (B = 0xefcdab89), ~A, ~B, 0xc3d2e1f0],
10 | words = [],
11 | s = unescape(encodeURI(b)) + '\x80',
12 | j = s.length;
13 |
14 | // See "Length bits" in notes
15 | words[(b = (--j / 4 + 2) | 15)] = j * 8;
16 |
17 | for (; ~j; ) {
18 | // j !== -1
19 | words[j >> 2] |= s.charCodeAt(j) << (8 * ~j--);
20 | // words[j >> 2] |= s.charCodeAt(j) << 24 - 8 * j--;
21 | }
22 |
23 | for (i = j = 0; i < b; i += 16) {
24 | A = h;
25 |
26 | for (
27 | ;
28 | j < 80;
29 | A = [
30 | A[4] +
31 | (W[j] = j < 16 ? ~~words[i + j] : (s * 2) | (s < 0)) + // s << 1 | s >>> 31
32 | 1518500249 +
33 | [(B & C) | (~B & D), (s = (B ^ C ^ D) + 341275144), ((B & C) | (B & D) | (C & D)) + 882459459, s + 1535694389][/* 0 | (j++ / 20)*/ (j++ / 5) >> 2] +
34 | (((s = A[0]) << 5) | (s >>> 27)),
35 | s,
36 | (B << 30) | (B >>> 2),
37 | C,
38 | D,
39 | ]
40 | ) {
41 | s = W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16];
42 | B = A[1];
43 | C = A[2];
44 | D = A[3];
45 | }
46 |
47 | // See "Integer safety" in notes
48 | for (j = 5; j; ) {
49 | h[--j] += A[j];
50 | }
51 |
52 | // j === 0
53 | }
54 |
55 | for (s = ''; j < 40; ) {
56 | // s += ((h[j >> 3] >> 4 * ~j++) & 15).toString(16);
57 | s += ((h[j >> 3] >> ((7 - j++) * 4)) & 15).toString(16);
58 | // s += ((h[j >> 3] >> -4 * ++j) & 15).toString(16);
59 | }
60 |
61 | return s;
62 | }
63 |
64 | module.exports = sha1;
65 |
--------------------------------------------------------------------------------
/lib/utils/view-helper.js:
--------------------------------------------------------------------------------
1 | const op = require('../core/op');
2 |
3 | class V {
4 | constructor(ctx) {
5 | this.ctx = ctx;
6 | this.request = ctx.request;
7 | this.response = ctx.response;
8 | this.site = op.config.site;
9 | }
10 |
11 | get navs() {
12 | const path = this.request.path;
13 | const q = this.request.query;
14 | const arr = [{ name: 'root' }];
15 | path.split('/')
16 | .filter((e) => e)
17 | .forEach((e) => {
18 | arr.push({ name: e });
19 | });
20 | if (path.endsWith('/')) {
21 | let p = './';
22 | for (let i = arr.length - 1; i >= 0; i--) {
23 | arr[i].href = p;
24 | p += '../';
25 | }
26 | if (q.id) {
27 | arr[arr.length - 1].href += '?id=' + encodeURIComponent(q.id);
28 | }
29 | } else {
30 | arr[arr.length - 1].href = (q.preview !== undefined ? '?preview' : '?') + this.appendReqQueryID;
31 | let p = './';
32 | for (let i = arr.length - 2; i >= 0; i--) {
33 | arr[i].href = p;
34 | p += '../';
35 | }
36 | }
37 | return arr;
38 | }
39 |
40 | get list() {
41 | return this.response.data.list;
42 | }
43 |
44 | get hasPrev() {
45 | return this.response.data.prevToken;
46 | }
47 |
48 | get prevHref() {
49 | return '?page=' + encodeURIComponent(this.response.data.prevToken) + this.appendReqQueryID;
50 | }
51 |
52 | get hasParent() {
53 | return this.request.path !== '/';
54 | }
55 |
56 | get hasNext() {
57 | return this.response.data.nextToken;
58 | }
59 |
60 | get nextHref() {
61 | return '?page=' + encodeURIComponent(this.response.data.nextToken) + this.appendReqQueryID;
62 | }
63 |
64 | get appendReqQueryID() {
65 | const id = this.request.query.id;
66 | return id ? '&id=' + encodeURIComponent(id) : '';
67 | }
68 |
69 | get isEmpty() {
70 | return this.response.data.list.length === 0;
71 | }
72 |
73 | previewHref(e, p = true) {
74 | if (e.type === 0) {
75 | return `${e.name}${e.id ? '?id=' + encodeURIComponent(e.id) : ''}${p ? (e.id ? '&preview' : '?preview') : ''}`;
76 | } else {
77 | return `${e.name}/${e.id ? '?id=' + encodeURIComponent(e.id) : ''}`;
78 | }
79 | }
80 |
81 | get file() {
82 | return this.response.data.file;
83 | }
84 |
85 | get previewType() {
86 | const f = this.file;
87 | const m = f.mime;
88 | if (m.startsWith('image/')) {
89 | return 'image';
90 | }
91 | if (m.startsWith('video/')) {
92 | return 'video';
93 | }
94 | if (m.startsWith('audio/')) {
95 | return 'audio';
96 | }
97 | if (['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'mpp', 'rtf', 'vsd', 'vsdx'].includes(f.name.slice(f.name.lastIndexOf('.') + 1))) {
98 | return 'office';
99 | }
100 | if (m.endsWith('pdf')) {
101 | return 'pdf';
102 | }
103 | if (f.size < 16 * 1024) {
104 | return 'text';
105 | }
106 | if (m.startsWith('text')) {
107 | return 'bigText';
108 | }
109 | return '';
110 | }
111 |
112 | // @warning 考虑放弃proxy功能
113 | get downloadUrl() {
114 | return (this.request.cookies.PROXY_DOWN || '') + this.response.data.file.url;
115 | }
116 |
117 | get hasPassword() {
118 | return this.response.data.error === 'Unauthorized';
119 | }
120 |
121 | get passwordHint() {
122 | const { type, field } = this.response.data.data;
123 | return field + ' ' + type;
124 | }
125 |
126 | get jsonData() {
127 | return JSON.stringify(this.response.data, null, 2);
128 | }
129 |
130 | get readme() {
131 | return ((this.ctx.$node || {}).$config || {}).readme || op.config.site.readme;
132 | }
133 |
134 | get readmeUrl() {
135 | return this.response.isList && this.response.data.list.find((e) => e.name === 'README.md') ? 'README.md' : '';
136 | }
137 |
138 | get cacheTime() {
139 | return this.response.data.cached;
140 | }
141 |
142 | get refreshHref() {
143 | const q = this.request.query;
144 | return '?refresh' + (q.preview === undefined ? '' : '&preview') + this.appendReqQueryID + (q.page ? '&page=' + encodeURIComponent(q.page) : '');
145 | }
146 |
147 | encodeURIComponent(u) {
148 | return encodeURIComponent(u);
149 | }
150 | }
151 |
152 | module.exports = V;
153 |
--------------------------------------------------------------------------------
/lib/views/art-runtime.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*! art-template@runtime | https://github.com/aui/art-template */
4 |
5 | var globalThis = typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
6 |
7 | var runtime = Object.create(globalThis);
8 | var ESCAPE_REG = /["&'<>]/;
9 |
10 | /**
11 | * 编码模板输出的内容
12 | * @param {any} content
13 | * @return {string}
14 | */
15 | runtime.$escape = function (content) {
16 | return xmlEscape(toString(content));
17 | };
18 |
19 | /**
20 | * 迭代器,支持数组与对象
21 | * @param {array|Object} data
22 | * @param {function} callback
23 | */
24 | runtime.$each = function (data, callback) {
25 | if (Array.isArray(data)) {
26 | for (var i = 0, len = data.length; i < len; i++) {
27 | callback(data[i], i);
28 | }
29 | } else {
30 | for (var _i in data) {
31 | callback(data[_i], _i);
32 | }
33 | }
34 | };
35 |
36 | // 将目标转成字符
37 | function toString(value) {
38 | if (typeof value !== 'string') {
39 | if (value === undefined || value === null) {
40 | value = '';
41 | } else if (typeof value === 'function') {
42 | value = toString(value.call(value));
43 | } else {
44 | value = JSON.stringify(value);
45 | }
46 | }
47 |
48 | return value;
49 | }
50 |
51 | // 编码 HTML 内容
52 | function xmlEscape(content) {
53 | var html = '' + content;
54 | var regexResult = ESCAPE_REG.exec(html);
55 | if (!regexResult) {
56 | return content;
57 | }
58 |
59 | var result = '';
60 | var i = void 0,
61 | lastIndex = void 0,
62 | char = void 0;
63 | for (i = regexResult.index, lastIndex = 0; i < html.length; i++) {
64 | switch (html.charCodeAt(i)) {
65 | case 34:
66 | char = '"';
67 | break;
68 | case 38:
69 | char = '&';
70 | break;
71 | case 39:
72 | char = ''';
73 | break;
74 | case 60:
75 | char = '<';
76 | break;
77 | case 62:
78 | char = '>';
79 | break;
80 | default:
81 | continue;
82 | }
83 |
84 | if (lastIndex !== i) {
85 | result += html.substring(lastIndex, i);
86 | }
87 |
88 | lastIndex = i + 1;
89 | result += char;
90 | }
91 |
92 | if (lastIndex !== i) {
93 | return result + html.substring(lastIndex, i);
94 | } else {
95 | return result;
96 | }
97 | }
98 |
99 | module.exports = runtime;
--------------------------------------------------------------------------------
/lib/views/art/simple.art:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ $V.site.name }}
8 |
9 |
10 |
11 |
12 |
13 | {{ set navs=$V.navs}}
14 | {{ each navs}}
15 | {{ if $index===0 }}
16 |
Home
17 | {{else}}
18 |
/
19 |
{{ $value.name }}
20 | {{ /if }}
21 | {{ /each }}
22 |
23 | {{ if response.isList}}
24 | {{ each $V.list }}
25 |
28 | {{ /each }}
29 | {{ if $V.hasNext }}
30 |
33 | {{ /if }}
34 | {{ else }}
35 |
36 |
{{ $V.jsonData }}
37 |
38 | {{ /if }}
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/lib/views/art/w.w.art:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ $V.site.name }}
13 |
31 |
32 |
33 |
41 |
42 |
50 | {{ if response.isList }}
51 |
52 |
53 |
54 |
55 | Name |
56 | Time |
57 | Size |
58 |
59 |
60 |
61 | {{ if $V.hasPrev }}
62 |
63 | 👆Previous... |
64 | |
65 | |
66 |
67 | {{ else if $V.hasParent }}
68 |
69 | 👈.. |
70 | |
71 | |
72 |
73 | {{ /if }}
74 |
75 | {{ each $V.list }}
76 |
77 | {{ ($value.type===0?'':'📁') + $value.name}} |
80 | {{ $value.time }} |
81 | {{ $value.size }} |
82 |
83 | {{ /each }}
84 |
85 | {{ if $V.hasNext }}
86 |
87 | 👇Next... |
88 | |
89 | |
90 |
91 | {{ /if }}
92 |
93 |
94 |
128 | {{ if $V.isEmpty }}
129 |
Empty Folder!
130 | {{ /if }}
131 |
132 |
133 | {{ else if response.isFile }}
134 |
135 | {{ set type=$V.previewType }}
136 | {{ set url=$V.downloadUrl }}
137 | {{ set oUrl=$V.previewHref($V.file,false)}}
138 |
147 |
148 |
149 | {{ if type === 'image' }}
150 |

151 | {{ else if type === 'video' || $V.file.name.endsWith('.m3u8') }}
152 |
153 |
154 |
155 |
156 |
163 | {{ else if type === 'audio' }}
164 |
165 | {{ else if type === 'office' }}
166 |
175 | {{ else if type==='pdf' }}
176 |
177 |
178 |
179 | {{ else if type==='text' }}
180 |
loading...
181 |
182 |
183 |
191 | {{ else if type==='bigText'}}
192 |
该文本文件太大, 不支持预览 :-(
193 | {{ else }}
194 |
此格式({{ $V.file.mime }})不支持预览 :-(
195 | {{ /if }}
196 |
197 |
198 |
204 |
205 | {{ else }}
206 |
207 | {{ if $V.hasPassword }}
208 |
218 | {{ /if }}
219 |
220 |
{{ response.message }}
221 |
{{ $V.jsonData }}
222 |
223 | {{ /if }}
224 |
225 |
226 |
227 |
{{ $V.readme }}
228 |
229 |
230 | {{ if $V.readmeUrl }}
231 |
234 | {{ /if }}
235 |
236 |
240 | {{@ $V.site.html }}
241 |
242 |
243 |
--------------------------------------------------------------------------------
/lib/views/art2js.js:
--------------------------------------------------------------------------------
1 | //https://github.com/kangax/html-minifier/issues/1076
2 | require('art-template/node_modules/html-minifier').minify = require('html-minifier-terser').minify;
3 |
4 | const fs = require('fs');
5 | const path = require('path');
6 | const ART_PATH = path.join(__dirname, 'art/');
7 | const JS_PATH = path.join(__dirname, 'js/');
8 | const art = require('art-template');
9 | const artOpt = {debug: false};
10 | module.exports = function (flag) {
11 | fs.readdirSync(ART_PATH).forEach(e => {
12 | const src = ART_PATH + e;
13 | const des = JS_PATH + e + '.js';
14 | if (!fs.existsSync(des) || fs.statSync(src).mtimeMs > fs.statSync(des).mtimeMs) {
15 | console.log("update: " + e);
16 | const r = art.compile(fs.readFileSync(src, 'utf-8'), artOpt);
17 | fs.writeFileSync(des, `const $imports = require('../art-runtime');module.exports={name:"${e}"};module.exports.render=` + r.toString(), {encoding: 'utf-8'});
18 | console.log("update success: " + e);
19 | require(des).render = r;
20 | } else {
21 | console.log("ignore: " + e);
22 | }
23 | //@important 仅为方便测试使用,release前需要手动运行一次,将数据写入js。
24 | const desJs = require(des);
25 | flag && fs.watchFile(src, stats => {
26 | desJs.render = art.compile(fs.readFileSync(src, 'utf-8'), artOpt);
27 | console.log('update file:' + e + ', ' + stats.mtime.toLocaleString());
28 | });
29 | });
30 | };
--------------------------------------------------------------------------------
/lib/views/js/simple.art.js:
--------------------------------------------------------------------------------
1 | const $imports = require('../art-runtime');module.exports={name:"simple.art"};module.exports.render=function($data){
2 | 'use strict'
3 | $data=$data||{}
4 | var $$out='',$escape=$imports.$escape,$V=$data.$V,navs=$data.navs,$each=$imports.$each,$value=$data.$value,$index=$data.$index,response=$data.response
5 | $$out+=""
8 | $$out+=$escape($V.site.name)
9 | $$out+=" "
10 | var navs=$V.navs
11 | $$out+=" "
12 | $each(navs,function($value,$index){
13 | $$out+=" "
14 | if($index===0){
15 | $$out+="
Home "
18 | }else{
19 | $$out+="
/ "
22 | $$out+=$escape($value.name)
23 | $$out+=" "
24 | }
25 | $$out+=" "
26 | })
27 | $$out+="
"
28 | if(response.isList){
29 | $$out+=" "
30 | $each($V.list,function($value,$index){
31 | $$out+="
"
36 | })
37 | $$out+=" "
38 | if($V.hasNext){
39 | $$out+="
"
42 | }
43 | $$out+=" "
44 | }else{
45 | $$out+="
"
46 | $$out+=$escape($V.jsonData)
47 | $$out+="
"
48 | }
49 | $$out+="
"
50 | return $$out
51 | }
--------------------------------------------------------------------------------
/lib/views/js/w.w.art.js:
--------------------------------------------------------------------------------
1 | const $imports = require('../art-runtime');module.exports={name:"w.w.art"};module.exports.render=function($data){
2 | 'use strict'
3 | $data=$data||{}
4 | var $$out='',$escape=$imports.$escape,$V=$data.$V,navs=$data.navs,$each=$imports.$each,$value=$data.$value,$index=$data.$index,response=$data.response,type=$data.type,url=$data.url,oUrl=$data.oUrl
5 | $$out+=""
8 | $$out+=$escape($V.site.name)
9 | $$out+=" "
24 | if(response.isList){
25 | $$out+="
"
54 | if($V.isEmpty){
55 | $$out+="
Empty Folder!
"
56 | }
57 | $$out+="
"
58 | }else if(response.isFile){
59 | $$out+=" "
60 | var type=$V.previewType
61 | $$out+=" "
62 | var url=$V.downloadUrl
63 | $$out+=" "
64 | var oUrl=$V.previewHref($V.file,false)
65 | $$out+="
"
68 | if(type === 'image'){
69 | $$out+="

"
72 | }else if(type === 'video' || $V.file.name.endsWith('.m3u8')){
73 | $$out+="
"
76 | }else if(type === 'audio'){
77 | $$out+="
"
80 | }else if(type === 'office'){
81 | $$out+="
"
86 | }else if(type==='pdf'){
87 | $$out+="
"
90 | }else if(type==='text'){
91 | $$out+="
loading...
"
94 | }else if(type==='bigText'){
95 | $$out+="
该文本文件太大, 不支持预览 :-(
"
96 | }else{
97 | $$out+="
此格式("
98 | $$out+=$escape($V.file.mime)
99 | $$out+=")不支持预览 :-(
"
100 | }
101 | $$out+="
"
102 | }else{
103 | $$out+=" "
104 | if($V.hasPassword){
105 | $$out+="
"
108 | }
109 | $$out+="
"
110 | $$out+=$escape(response.message)
111 | $$out+="
"
112 | $$out+=$escape($V.jsonData)
113 | $$out+="
"
114 | }
115 | $$out+="
"
118 | $$out+=$escape($V.readme)
119 | $$out+="
"
120 | if($V.readmeUrl){
121 | $$out+=" "
122 | }
123 | $$out+="
"
128 | $$out+=$V.site.html
129 | $$out+="
"
130 | return $$out
131 | }
--------------------------------------------------------------------------------
/lib/views/js/w.w.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | render: () => {}
3 | };
4 |
--------------------------------------------------------------------------------
/ncc/build.js:
--------------------------------------------------------------------------------
1 | //修改文件后 可以通过此脚本重新编译发布
2 | const {readdirSync, writeFileSync} = require('fs');
3 | const ncc = require('@vercel/ncc');
4 |
5 | const APP_PATH = require('path').resolve(__dirname, '../lib');
6 | const DIST_PATH = require('path').resolve(__dirname, '../ncc');
7 |
8 | readdirSync(APP_PATH + '/starters').forEach(name => {
9 | if (name.startsWith('local')) {
10 | return;
11 | }
12 | ncc(APP_PATH + '/starters/' + name, {
13 | // provide a custom cache path or disable caching
14 | cache: false,
15 | // externals to leave as requires of the build
16 | externals: [],
17 | // directory outside of which never to emit assets
18 | filterAssetBase: APP_PATH, // default
19 | minify: false, // default
20 | sourceMap: false, // default
21 | sourceMapBasePrefix: '../', // default treats sources as output-relative
22 | // when outputting a sourcemap, automatically include
23 | // source-map-support in the output file (increases output by 32kB).
24 | sourceMapRegister: true, // default
25 | watch: false, // default
26 | license: '', // default does not generate a license file
27 | v8cache: false, // default
28 | quiet: false, // default
29 | debugLog: false // default
30 | }).then(({code}) => {
31 | if (name.startsWith('cf')) {
32 | code = 'globalThis.__dirname="";\n' + code;
33 | }
34 | writeFileSync(DIST_PATH + '/ncc_' + name, code);
35 | });
36 | });
37 |
38 |
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "ukuq",
3 | "bugs": {
4 | "url": "https://github.com/ukuq/onepoint/issues"
5 | },
6 | "dependencies": {},
7 | "description": "a tiny file index and manage program",
8 | "devDependencies": {
9 | "@vercel/ncc": "^0.28.6",
10 | "art-template": "^4.13.2",
11 | "eslint": "^7.16.0",
12 | "eslint-config-prettier": "^7.1.0",
13 | "eslint-plugin-prettier": "^3.3.0",
14 | "html-minifier-terser": "^5.1.1",
15 | "prettier": "^2.2.1"
16 | },
17 | "files": [
18 | "lib"
19 | ],
20 | "homepage": "https://github.com/ukuq/onepoint#readme",
21 | "keywords": [
22 | "onepoint",
23 | "onedrive",
24 | "google-drive",
25 | "scf",
26 | "serverless"
27 | ],
28 | "license": "MIT",
29 | "main": "lib/app.js",
30 | "name": "onepoint",
31 | "prettier": {
32 | "printWidth": 233,
33 | "singleQuote": true,
34 | "tabWidth": 4,
35 | "trailingComma": "es5"
36 | },
37 | "repository": {
38 | "type": "git",
39 | "url": "git+https://github.com/ukuq/onepoint.git"
40 | },
41 | "scripts": {
42 | "__local_start": "node lib/starters/local-test.js",
43 | "__pre_commit": "node tmp/pre-commit.js",
44 | "build:ncc": "node ncc/build.js",
45 | "format": "eslint \"**/*.js\" --fix && prettier \"**/*.{js,json}\" --write",
46 | "format:check": "eslint \"**/*.js\" && prettier \"**/*.{js,json}\" --check",
47 | "start": "node lib/starters/node-http.js"
48 | },
49 | "version": "2.0.1",
50 | "version2": "210620"
51 | }
52 |
--------------------------------------------------------------------------------
/worker/README.md:
--------------------------------------------------------------------------------
1 | ## Cloudflare Workers 部署
2 |
3 | ### 新建 Worker
4 | 
5 |
6 | ### 粘贴代码
7 |
8 | https://github.com/ukuq/onepoint/blob/master/ncc/ncc_cf-worker.js
9 |
10 | 或者 https://raw.githubusercontent.com/ukuq/onepoint/master/ncc/ncc_cf-worker.js
11 |
12 | 代码较多,保存可能要费点时间,不要心急!
13 |
14 | 
15 |
16 | ### 返回上一级,新建KV桶,名字随意
17 |
18 | 
19 | 
20 |
21 | ### 绑定KV桶,变量名设置为OPCONFIG
22 |
23 | 
24 |
25 | ### DEMO
26 |
27 | https://onepoint.onesrc.workers.dev/
28 |
29 | ### DEV
30 |
31 | 如需修改代码,可以 git clone,修改前后使用 ncc 打包
32 |
33 |
--------------------------------------------------------------------------------