init
Massimo Melina committed
Dec 8, 2021 at 00:17 UTC
054e7d9b05d94a27c75233526cfe0850af2ed5a8
9 files changed
+1323
.gitignore
new
+2
@@ -0,0 +1,2 @@
1
+node_modules
2
+.idea
\ No newline at end of file
frontend/index.html
new
+33
@@ -0,0 +1,33 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+ <meta charset="UTF-8" />
5
+ <title>HFS 3 front end</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <link rel="stylesheet" type="text/css" href="/~/frontend/main.css" />
8
+
9
+ <!--[if lt IE 9 ]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
10
+ <script src='/socket.io/socket.io.js'></script>
11
+ <script src='/~/jquery-1.11.3.js'></script>
12
+ <script src='/~/frontend/main.js'></script>
13
+ </head>
14
+<body>
15
+<div id="control-tiles">
16
+ <div id='folder'></div>
17
+ <div id='folder-info'></div>
18
+ <div>
19
+ <label>View mode</label>
20
+ <select id='mode'><option>tiles<option>list</select>
21
+ </div>
22
+ <div>
23
+ <label>Order</label>
24
+ <select id='order'><option value=''>none<option value='label' selected>name<option>type<option>size</select>
25
+ </div>
26
+ <div>
27
+ <label>Pagination</label>
28
+ <select id='pagination'><option value=''>none<option>50<option selected>200<option>500</select>
29
+ </div>
30
+</div>
31
+<ul id='items'></ul>
32
+</body>
33
+</html>
frontend/main.css
new
+54
@@ -0,0 +1,54 @@
1
+body { font:10pt verdana, arial, sans-serif; }
2
+a img { border:0; } /* conform IE */
3
+
4
+#items { list-style:none; padding:0; margin-top:1em; }
5
+#control-tiles { display: inline; }
6
+#control-tiles > div {
7
+ display:inline-block;
8
+ border-left: 5px solid #bbb;
9
+ background-color: #eee;
10
+ padding: 0.3em 1em;
11
+ margin: 0.1em 0;
12
+ color: #777;
13
+ line-height: 2em;
14
+}
15
+#folder { font-size:1.6em; font-weight:bold; word-break:break-all; display:block !important; padding-left:0.5em !important; }
16
+#folder img { height:1em; padding: 0 0.1em; }
17
+#folder a { text-decoration:none; }
18
+#folder a:hover { text-decoration:underline; }
19
+
20
+#num-items { min-width:3em; display: inline-block; font-weight:bold; }
21
+
22
+.full-label { position:absolute; padding-right:1em; text-align:left; background-color:#eee; }
23
+
24
+/* tiles */
25
+[mode=tiles] #items li { display:inline-block; } /* without this, the LI has height:0 */
26
+[mode=tiles] #items li.forced-br { display:block; } /* used for easeing the CPU */
27
+[mode=tiles] .item-link { float:left; overflow:hidden; width:8.2em; height:9.1em; /* this 0.1 more ensure the content doesn't go over for very little causing necessary effects */
28
+ text-align:center; text-decoration:none;
29
+ margin:1px; /* reserve space for the border on hover */
30
+}
31
+[mode=tiles].hover .item-link:hover {
32
+ background:#ddd;
33
+ border:1px solid #bbb; margin:0; /* replace margin with border */
34
+}
35
+[mode=tiles].hover .item-link:hover + .item-details { display:block; float:left; }
36
+
37
+[mode=tiles] .item-label { display:block; padding:0 0.5em; margin:3px; word-wrap:break-word; }
38
+[mode=tiles] .item-details { display:none; }
39
+[mode=tiles] .item-details-wrapper { position:absolute; background:#ffe; border:1px solid #eec; padding:0.2em 0.4em; }
40
+[mode=tiles] .full-label { max-width:17em; border:1px solid #bbb; padding:0.2em 0.5em; }
41
+
42
+/* list */
43
+[mode=list] li { border-bottom:1px solid #eee; height:1.5em; }
44
+[mode=list] li:nth-of-type(odd) { background:#eee; } /* stripes */
45
+[mode=list] .item-link { clear:left; float:left; text-decoration:none;
46
+ width:80%; max-width:30em; height:1.5em; overflow:hidden;
47
+ margin-right:1em; /* leave some space to breathe */
48
+ white-space:nowrap; /* show as much as you can, even half-words, otherwise it will wrap under */
49
+}
50
+[mode=list] .full-label { white-space:normal; } /* re-enable wrapping */
51
+[mode=list] .item-link img { height:1.5em; vertical-align:middle; float:left; }
52
+[mode=list] .item-label { margin-left:0.5em; margin-right:1em; }
53
+[mode=list] .item-type { display:none; }
54
+[mode=list] .item-size { display:inline; min-width:7em; }
frontend/main.js
new
+216
@@ -0,0 +1,216 @@
1
+/**
2
+ * @author Massimo Melina <a@rejetto.com>
3
+ */
4
+
5
+function loadJS(libs) {
6
+ libs = libs.split(',');
7
+ for (var i=libs.length; i--;) {
8
+ document.write("<script src='/~/"+libs[i]+".js'></script>");
9
+ }
10
+}
11
+
12
+loadJS('extending,cs-shared,misc');
13
+
14
+
15
+var socket, currentFolder, listFromServer, currentMode, foldersBefore=1, currentPage= 0;
16
+
17
+// this object will hold all the customizable stuff, that is added in file "tpl.js"
18
+var TPL = function(event) {
19
+ var fun = TPL[currentMode+'_'+event] || TPL[event];
20
+ if (!fun) return;
21
+ var newArgs = [];
22
+ for (var i=1,a=arguments,l=a.length; i<l; ++i)
23
+ newArgs.push(a[i]);
24
+ fun.apply(this, newArgs);
25
+};
26
+
27
+loadJS('frontend/tpl,frontend/vfs');
28
+
29
+// understand the requested folder from the URL
30
+function getURLfolder() {
31
+ var sub = location.hash.substr(1);
32
+ return sub.startsWith('/') ? sub : location.pathname+sub;
33
+} // getURLfolder
34
+
35
+$(function onJQ(){ // dom ready
36
+
37
+ (function speedSetup() {
38
+
39
+ function chooseSpeed(q, map, def){
40
+ for (var k in map) {
41
+ if (q <= k) return map[k];
42
+ }
43
+ return def;
44
+ } // chooseSpeed
45
+
46
+ $('#pagination').val( chooseSpeed(benchmark(), {
47
+ 5: 500,
48
+ 50: 200
49
+ }, 50) );
50
+ })();
51
+
52
+ socket = io.connect(window.location.origin);
53
+
54
+ socket.on('connect', function onIO(){ // socket ready
55
+ log('connected');
56
+
57
+ var saved = JSON.parse(getCookie('settings')) || {};
58
+ ['Order','Mode','Pagination'].forEach(function(v){
59
+ var lc = v.low();
60
+ var update = window['update'+v];
61
+ update(saved[lc]); // try to restore last options
62
+ // change things at user will
63
+ $('#'+lc).change(function(){
64
+ update();
65
+ redrawItems();
66
+ });
67
+ });
68
+
69
+ loadFolder(getURLfolder(), function onFolder(){ // folder ready
70
+
71
+ /* support for the BACK button: when the user clicks the BACK button, the address bar changes going out of
72
+ sync with the view. We fix it ASAP. I don't know an event for the address bar, so i'm polling. */
73
+ repeat(300, function(){
74
+ var shouldBe = getURLfolder();
75
+ if (currentFolder != shouldBe) {
76
+ loadFolder(shouldBe);
77
+ }
78
+ });
79
+
80
+ }); // don't redraw
81
+ });//socket connect
82
+
83
+ socket.on('vfs.changed', function(data){
84
+ log('vfs.changed',data);
85
+ // it would be nicer to update only the changed item, but for now easily reload the whole dir
86
+ var folder = data.uri.endsWith('/') ? data.uri : dirname(data.uri);
87
+ if (folder === currentFolder) {
88
+ loadFolder();
89
+ }
90
+ });
91
+
92
+});
93
+
94
+// ask the server for the items list of the specified folder, then sort and display
95
+function loadFolder(path /** optional */, cb /** optional */) {
96
+ if (path) currentFolder = path;
97
+ // breadcrumbs
98
+ $('#folder').html(
99
+ '<a href="/#"><img src="'+getPicURI('home')+'"/></a>'+
100
+ // build pairs text/link
101
+ decodeURI(currentFolder).split('/').filter('A').map('["/"+A, "/#"+C.slice(0,B+1).join("/")+"/"]')
102
+ // then to html
103
+ .map('$("<a>").text(A[0]).attr({href:A[1]})[0].outerHTML').join('')
104
+ );
105
+
106
+ socket.emit('get list', { path:currentFolder }, function onGetList(reply){
107
+ if (showError(reply)) return;
108
+ listFromServer = reply; // hold it in a global variable, to not loose it
109
+ convertList(reply);
110
+ $('#folder-info').html("Items: <span id='num-items'>{0}</span>".x(reply.items.length));
111
+ sortItems();
112
+ redrawItems();
113
+ if (typeof cb == 'function') {
114
+ cb();
115
+ }
116
+ });
117
+} // loadFolder
118
+
119
+function showError(reply) {
120
+ if (reply.ok) return false;
121
+ if (reply.error) alert('Error: '+reply.error);
122
+ return true;
123
+} // showError
124
+
125
+// convert file list format: expands some field-names
126
+function convertList(serverReply) {
127
+ if (!serverReply) return;
128
+ var a = serverReply.items;
129
+ if (!a) return;
130
+ for (var i=a.length; i--;) {
131
+ var o = a[i]._remapKeys({ n:'label', t:'type', s:'size'});
132
+ switch (o.type) {
133
+ case undefined: // no type is default type: file
134
+ o.type = 'file'; // now continue with the case 'file'
135
+ case 'file': // for files, calculate specific type
136
+ var t = nameToType(o.label);
137
+ if (t) o.type = t;
138
+ break;
139
+ case 'link':
140
+ o.url = o.resource;
141
+ break;
142
+ }
143
+ o.url = o.url || escapeLink(currentFolder+o.label)+(o.type == 'folder' ? '/' : '');
144
+ }
145
+} // convertList
146
+
147
+function escapeLink(s) {
148
+ //return encodeURI(s)
149
+ return s.replace('"','"').replace("'", ''').replace('%','%25')
150
+}
151
+
152
+function updateSettingsCookie(settings) {
153
+ var v = getCookie('settings');
154
+ try { v = JSON.parse(v) }
155
+ catch(e) {}
156
+ if (!v || typeof v != 'object') v = {};
157
+ v._expand(settings);
158
+ setCookie('settings', JSON.stringify(v));
159
+} // updateSettingsCookie
160
+
161
+function updateMode(v){
162
+ // if no value is passed, then read it from the DOM, otherwise write it in the DOM
163
+ if (!v || !v.length) v = $('#mode').val();
164
+ else $('#mode').val(v);
165
+
166
+ currentMode = v; // global
167
+ updateSettingsCookie({ mode: v }); // remember
168
+ $('html').attr('mode', v);
169
+} // updateMode
170
+
171
+function updatePagination(v){
172
+ // if no value is passed, then read it from the DOM, otherwise write it in the DOM
173
+ if (!v || !v.length) v = $('#pagination').val();
174
+ else $('#pagination').val(v);
175
+
176
+ currentPagination = v; // global
177
+ updateSettingsCookie({ pagination: v }); // remember
178
+ redrawItems();
179
+} // updatePagination
180
+
181
+function updateOrder(v) {
182
+ // if no value is passed, then read it from the DOM, otherwise write it in the DOM
183
+ if (!v || !v.length) v = $('#order').val();
184
+ else $('#order').val(v);
185
+
186
+ currentOrder = v; // global
187
+ updateSettingsCookie({ order: v }); // remember
188
+ if (v) {
189
+ $('#order option[value=""]').remove(); // after we have sorted the items there's no way to return to the original order, so let's hide this option
190
+ }
191
+ sortItems();
192
+} // updateOrder
193
+
194
+function sortItems() {
195
+ if (!currentOrder || !listFromServer) return; // no job
196
+
197
+ listFromServer.items.sort(function cb(a,b,field){
198
+ field = field || currentOrder;
199
+ if (field != 'type' && foldersBefore) { // if field is 'type', then the folders are always put at the top
200
+ var res = -cmp(a['type'] == 'folder', b['type'] == 'folder');
201
+ if (res) return res;
202
+ }
203
+ var va = a[field];
204
+ var vb = b[field];
205
+ switch (field) {
206
+ case 'label':
207
+ va=va.low(), vb=vb.low();
208
+ break;
209
+ case 'type':
210
+ if (va == 'folder') va=''; // trick to get folders at the top
211
+ if (vb == 'folder') vb='';
212
+ break;
213
+ }
214
+ return cmp(va,vb) || (field=='label' ? 0 : cb(a,b,'label'));
215
+ });
216
+} // sortItems
frontend/tpl.js
new
+17
@@ -0,0 +1,17 @@
1
+assert(TPL, 'tpl');
2
+
3
+TPL.item =
4
+ "<a href=\"{url}\" class='item-link'><img src='{icon-file}' class='item-icon' /><span class='item-label'>{label}</span></a>"
5
+ +"<div class='item-details'><div class='item-details-wrapper'>"
6
+ +"<div class='item-type'>{type}</div>"
7
+ +"<div class='item-size'>{size}</div>"
8
+ +"</div></div>";
9
+
10
+TPL.list_onObjectItem = function(item) {
11
+ item.size = item.size ? formatBytes(item.size) : 'folder';
12
+};
13
+
14
+TPL.tiles_onObjectItem = function(item) {
15
+ item.type = 'Type: '+item.type;
16
+ item.size = item.size ? 'Size: '+formatBytes(item.size) : '';
17
+};
frontend/vfs.js
new
+118
@@ -0,0 +1,118 @@
1
+$(function(){
2
+ $('#items').on({
3
+ mouseenter: function(){
4
+ if (!$(this).isOverflowed()) return; // is our label clipped?
5
+ var lbl = $(this).find('.item-label');
6
+ // make some changes so it's hopefully fully visible. We actually just mark it, leaving the real work to your css rules.
7
+ lbl.addClass('full-label');
8
+ },
9
+ mouseleave: function(){
10
+ // undo changes made few lines above
11
+ var lbl = $(this).find('.full-label');
12
+ lbl.removeClass('full-label');
13
+ if (lbl.data('remove bg')) {
14
+ lbl.css('background-color','');
15
+ lbl.removeData('remove bg',null);
16
+ }
17
+ },
18
+ click: itemClickHandler
19
+ }, '.item-link');
20
+
21
+ /* display:float used by 'tiles' is CPU expensive when we get many items (500+ on a core2duo@2.1).
22
+ * To ease this task we periodically set fixed line breaks.
23
+ */
24
+ var last;
25
+ repeat(100, function(){
26
+ if (currentMode !== 'tiles') {
27
+ last = null;
28
+ return;
29
+ }
30
+ var d = $('#items');
31
+ var x = d.children(':first').width();
32
+ if (!x) return; // no items
33
+ var n = Math.floor((d.width() - 5) / x); // leave a small margin, otherwise the browser decides it is not truly fitting, and you get an undesired wrapping
34
+ if ($.support.hover) n--; // we leave some space for popup properties
35
+ if (n === last) return;
36
+ last = n;
37
+ d.children('.forced-br').removeClass('forced-br'); // clean
38
+ d.children(':nth-child({0}n+1):not(:first)'.x(n)).addClass('forced-br'); // set new br
39
+ });
40
+
41
+
42
+});
43
+
44
+// rebuild the DOM of items
45
+function redrawItems() {
46
+ var x = $('#items').empty();
47
+
48
+ if (!listFromServer) return;
49
+
50
+ // add a link to the parent folder
51
+ var cf = currentFolder; // shortcut
52
+ if (cf > '/') {
53
+ addItem({
54
+ label: '↑↑',
55
+ url: dirname(cf).includeTrailing('/'),
56
+ type: 'folder',
57
+ icon: 'folder'
58
+ });
59
+ }
60
+
61
+ var n = listFromServer.items.length;
62
+ var pages = Math.max(1, Math.ceil(n/currentPagination));
63
+ if (currentPage >= pages) currentPage = pages-1;
64
+ var overflow = (currentPagination && currentPagination < n);
65
+ var ofs = overflow ? currentPage*currentPagination : 0;
66
+ var max = currentPagination ? Math.min(currentPagination, n-ofs) : n;
67
+
68
+ $('#paginator').remove();
69
+ if (overflow) { // draw a paginator
70
+ var d = $("<div id='paginator'>").insertBefore('#items');
71
+ d.append("Pages ");
72
+ for (var i=0; i<pages; i++) {
73
+ $("<button>").text(i+1)
74
+ .attr({page:i, disabled:i===currentPage}) // highlight current page (by disabling the button)
75
+ .appendTo(d)
76
+ .click(function(){
77
+ currentPage = +$(this).attr('page');if (it.jquery)
78
+ redrawItems();
79
+ })
80
+ }
81
+ }
82
+
83
+ for (var a=listFromServer.items, i=0; i<max; ++i) {
84
+ var o = a[ofs+i]._clone(); // The item will be manipulated (also inside addItem), and we don't want to make this changes persistent over view modes
85
+ o.icon = o.type;
86
+ addItem(o);
87
+ }
88
+} // redrawItems
89
+
90
+// build the DOM for the single item, applying possible filtering functions
91
+function addItem(it) {
92
+ it._expand({'icon-file':getIconURI(it.icon)}); // make this additions before the hook, so it can change these too
93
+ TPL('onObjectItem', it); // custom treatment, especially mode-based
94
+ $('<li>').append(TPL.item.format(it))
95
+ .appendTo('#items');
96
+} // addItem
97
+
98
+// called when an item is clicked
99
+function itemClickHandler(ev) {
100
+ var x = $(this);
101
+ var h = x.attr('href');
102
+ if (h.substr(-1) == '/') {
103
+ if (location.pathname != '/') { // reloads the page to have a neater URL
104
+ location = '/#'+h.substr(1);
105
+ return false;
106
+ }
107
+
108
+ location.hash = (h.startsWith(location.pathname)) ? h.substr(location.pathname.length) : h;
109
+ var loader = $("<img src='/~/pics/loader.gif'>").css(x.find('.item-icon').offset()._expand({position:'absolute'})).appendTo('body');
110
+ loadFolder(h, function(){ loader.remove() });
111
+ return false;
112
+ }
113
+ if (!x.attr('target')) {
114
+ x.attr('target', 'preview'); // open the file in a new window so the app doesn't stop
115
+ }
116
+ return true;
117
+} // itemClickHandler
118
+
package-lock.json
new
+855
@@ -0,0 +1,855 @@
1
+{
2
+ "name": "hfs4",
3
+ "lockfileVersion": 2,
4
+ "requires": true,
5
+ "packages": {
6
+ "": {
7
+ "dependencies": {
8
+ "koa": "^2.13.4",
9
+ "koa-static": "^5.0.0"
10
+ }
11
+ },
12
+ "node_modules/accepts": {
13
+ "version": "1.3.7",
14
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
15
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
16
+ "dependencies": {
17
+ "mime-types": "~2.1.24",
18
+ "negotiator": "0.6.2"
19
+ },
20
+ "engines": {
21
+ "node": ">= 0.6"
22
+ }
23
+ },
24
+ "node_modules/cache-content-type": {
25
+ "version": "1.0.1",
26
+ "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
27
+ "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
28
+ "dependencies": {
29
+ "mime-types": "^2.1.18",
30
+ "ylru": "^1.2.0"
31
+ },
32
+ "engines": {
33
+ "node": ">= 6.0.0"
34
+ }
35
+ },
36
+ "node_modules/co": {
37
+ "version": "4.6.0",
38
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
39
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
40
+ "engines": {
41
+ "iojs": ">= 1.0.0",
42
+ "node": ">= 0.12.0"
43
+ }
44
+ },
45
+ "node_modules/content-disposition": {
46
+ "version": "0.5.3",
47
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
48
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
49
+ "dependencies": {
50
+ "safe-buffer": "5.1.2"
51
+ },
52
+ "engines": {
53
+ "node": ">= 0.6"
54
+ }
55
+ },
56
+ "node_modules/content-type": {
57
+ "version": "1.0.4",
58
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
59
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
60
+ "engines": {
61
+ "node": ">= 0.6"
62
+ }
63
+ },
64
+ "node_modules/cookies": {
65
+ "version": "0.8.0",
66
+ "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
67
+ "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
68
+ "dependencies": {
69
+ "depd": "~2.0.0",
70
+ "keygrip": "~1.1.0"
71
+ },
72
+ "engines": {
73
+ "node": ">= 0.8"
74
+ }
75
+ },
76
+ "node_modules/debug": {
77
+ "version": "4.3.3",
78
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
79
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
80
+ "dependencies": {
81
+ "ms": "2.1.2"
82
+ },
83
+ "engines": {
84
+ "node": ">=6.0"
85
+ },
86
+ "peerDependenciesMeta": {
87
+ "supports-color": {
88
+ "optional": true
89
+ }
90
+ }
91
+ },
92
+ "node_modules/deep-equal": {
93
+ "version": "1.0.1",
94
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
95
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
96
+ },
97
+ "node_modules/delegates": {
98
+ "version": "1.0.0",
99
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
100
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
101
+ },
102
+ "node_modules/depd": {
103
+ "version": "2.0.0",
104
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
105
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
106
+ "engines": {
107
+ "node": ">= 0.8"
108
+ }
109
+ },
110
+ "node_modules/destroy": {
111
+ "version": "1.0.4",
112
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
113
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
114
+ },
115
+ "node_modules/ee-first": {
116
+ "version": "1.1.1",
117
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
118
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
119
+ },
120
+ "node_modules/encodeurl": {
121
+ "version": "1.0.2",
122
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
123
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
124
+ "engines": {
125
+ "node": ">= 0.8"
126
+ }
127
+ },
128
+ "node_modules/escape-html": {
129
+ "version": "1.0.3",
130
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
131
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
132
+ },
133
+ "node_modules/fresh": {
134
+ "version": "0.5.2",
135
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
136
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
137
+ "engines": {
138
+ "node": ">= 0.6"
139
+ }
140
+ },
141
+ "node_modules/has-symbols": {
142
+ "version": "1.0.2",
143
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
144
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
145
+ "engines": {
146
+ "node": ">= 0.4"
147
+ },
148
+ "funding": {
149
+ "url": "https://github.com/sponsors/ljharb"
150
+ }
151
+ },
152
+ "node_modules/has-tostringtag": {
153
+ "version": "1.0.0",
154
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
155
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
156
+ "dependencies": {
157
+ "has-symbols": "^1.0.2"
158
+ },
159
+ "engines": {
160
+ "node": ">= 0.4"
161
+ },
162
+ "funding": {
163
+ "url": "https://github.com/sponsors/ljharb"
164
+ }
165
+ },
166
+ "node_modules/http-assert": {
167
+ "version": "1.5.0",
168
+ "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
169
+ "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
170
+ "dependencies": {
171
+ "deep-equal": "~1.0.1",
172
+ "http-errors": "~1.8.0"
173
+ },
174
+ "engines": {
175
+ "node": ">= 0.8"
176
+ }
177
+ },
178
+ "node_modules/http-errors": {
179
+ "version": "1.8.1",
180
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
181
+ "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
182
+ "dependencies": {
183
+ "depd": "~1.1.2",
184
+ "inherits": "2.0.4",
185
+ "setprototypeof": "1.2.0",
186
+ "statuses": ">= 1.5.0 < 2",
187
+ "toidentifier": "1.0.1"
188
+ },
189
+ "engines": {
190
+ "node": ">= 0.6"
191
+ }
192
+ },
193
+ "node_modules/http-errors/node_modules/depd": {
194
+ "version": "1.1.2",
195
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
196
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
197
+ "engines": {
198
+ "node": ">= 0.6"
199
+ }
200
+ },
201
+ "node_modules/inherits": {
202
+ "version": "2.0.4",
203
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
204
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
205
+ },
206
+ "node_modules/is-generator-function": {
207
+ "version": "1.0.10",
208
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
209
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
210
+ "dependencies": {
211
+ "has-tostringtag": "^1.0.0"
212
+ },
213
+ "engines": {
214
+ "node": ">= 0.4"
215
+ },
216
+ "funding": {
217
+ "url": "https://github.com/sponsors/ljharb"
218
+ }
219
+ },
220
+ "node_modules/keygrip": {
221
+ "version": "1.1.0",
222
+ "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
223
+ "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
224
+ "dependencies": {
225
+ "tsscmp": "1.0.6"
226
+ },
227
+ "engines": {
228
+ "node": ">= 0.6"
229
+ }
230
+ },
231
+ "node_modules/koa": {
232
+ "version": "2.13.4",
233
+ "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
234
+ "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==",
235
+ "dependencies": {
236
+ "accepts": "^1.3.5",
237
+ "cache-content-type": "^1.0.0",
238
+ "content-disposition": "~0.5.2",
239
+ "content-type": "^1.0.4",
240
+ "cookies": "~0.8.0",
241
+ "debug": "^4.3.2",
242
+ "delegates": "^1.0.0",
243
+ "depd": "^2.0.0",
244
+ "destroy": "^1.0.4",
245
+ "encodeurl": "^1.0.2",
246
+ "escape-html": "^1.0.3",
247
+ "fresh": "~0.5.2",
248
+ "http-assert": "^1.3.0",
249
+ "http-errors": "^1.6.3",
250
+ "is-generator-function": "^1.0.7",
251
+ "koa-compose": "^4.1.0",
252
+ "koa-convert": "^2.0.0",
253
+ "on-finished": "^2.3.0",
254
+ "only": "~0.0.2",
255
+ "parseurl": "^1.3.2",
256
+ "statuses": "^1.5.0",
257
+ "type-is": "^1.6.16",
258
+ "vary": "^1.1.2"
259
+ },
260
+ "engines": {
261
+ "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
262
+ }
263
+ },
264
+ "node_modules/koa-compose": {
265
+ "version": "4.1.0",
266
+ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
267
+ "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
268
+ },
269
+ "node_modules/koa-convert": {
270
+ "version": "2.0.0",
271
+ "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
272
+ "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
273
+ "dependencies": {
274
+ "co": "^4.6.0",
275
+ "koa-compose": "^4.1.0"
276
+ },
277
+ "engines": {
278
+ "node": ">= 10"
279
+ }
280
+ },
281
+ "node_modules/koa-send": {
282
+ "version": "5.0.1",
283
+ "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
284
+ "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
285
+ "dependencies": {
286
+ "debug": "^4.1.1",
287
+ "http-errors": "^1.7.3",
288
+ "resolve-path": "^1.4.0"
289
+ },
290
+ "engines": {
291
+ "node": ">= 8"
292
+ }
293
+ },
294
+ "node_modules/koa-static": {
295
+ "version": "5.0.0",
296
+ "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
297
+ "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
298
+ "dependencies": {
299
+ "debug": "^3.1.0",
300
+ "koa-send": "^5.0.0"
301
+ },
302
+ "engines": {
303
+ "node": ">= 7.6.0"
304
+ }
305
+ },
306
+ "node_modules/koa-static/node_modules/debug": {
307
+ "version": "3.2.7",
308
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
309
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
310
+ "dependencies": {
311
+ "ms": "^2.1.1"
312
+ }
313
+ },
314
+ "node_modules/media-typer": {
315
+ "version": "0.3.0",
316
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
317
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
318
+ "engines": {
319
+ "node": ">= 0.6"
320
+ }
321
+ },
322
+ "node_modules/mime-db": {
323
+ "version": "1.51.0",
324
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
325
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
326
+ "engines": {
327
+ "node": ">= 0.6"
328
+ }
329
+ },
330
+ "node_modules/mime-types": {
331
+ "version": "2.1.34",
332
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
333
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
334
+ "dependencies": {
335
+ "mime-db": "1.51.0"
336
+ },
337
+ "engines": {
338
+ "node": ">= 0.6"
339
+ }
340
+ },
341
+ "node_modules/ms": {
342
+ "version": "2.1.2",
343
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
344
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
345
+ },
346
+ "node_modules/negotiator": {
347
+ "version": "0.6.2",
348
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
349
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
350
+ "engines": {
351
+ "node": ">= 0.6"
352
+ }
353
+ },
354
+ "node_modules/on-finished": {
355
+ "version": "2.3.0",
356
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
357
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
358
+ "dependencies": {
359
+ "ee-first": "1.1.1"
360
+ },
361
+ "engines": {
362
+ "node": ">= 0.8"
363
+ }
364
+ },
365
+ "node_modules/only": {
366
+ "version": "0.0.2",
367
+ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
368
+ "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
369
+ },
370
+ "node_modules/parseurl": {
371
+ "version": "1.3.3",
372
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
373
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
374
+ "engines": {
375
+ "node": ">= 0.8"
376
+ }
377
+ },
378
+ "node_modules/path-is-absolute": {
379
+ "version": "1.0.1",
380
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
381
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
382
+ "engines": {
383
+ "node": ">=0.10.0"
384
+ }
385
+ },
386
+ "node_modules/resolve-path": {
387
+ "version": "1.4.0",
388
+ "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
389
+ "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
390
+ "dependencies": {
391
+ "http-errors": "~1.6.2",
392
+ "path-is-absolute": "1.0.1"
393
+ },
394
+ "engines": {
395
+ "node": ">= 0.8"
396
+ }
397
+ },
398
+ "node_modules/resolve-path/node_modules/depd": {
399
+ "version": "1.1.2",
400
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
401
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
402
+ "engines": {
403
+ "node": ">= 0.6"
404
+ }
405
+ },
406
+ "node_modules/resolve-path/node_modules/http-errors": {
407
+ "version": "1.6.3",
408
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
409
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
410
+ "dependencies": {
411
+ "depd": "~1.1.2",
412
+ "inherits": "2.0.3",
413
+ "setprototypeof": "1.1.0",
414
+ "statuses": ">= 1.4.0 < 2"
415
+ },
416
+ "engines": {
417
+ "node": ">= 0.6"
418
+ }
419
+ },
420
+ "node_modules/resolve-path/node_modules/inherits": {
421
+ "version": "2.0.3",
422
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
423
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
424
+ },
425
+ "node_modules/resolve-path/node_modules/setprototypeof": {
426
+ "version": "1.1.0",
427
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
428
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
429
+ },
430
+ "node_modules/safe-buffer": {
431
+ "version": "5.1.2",
432
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
433
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
434
+ },
435
+ "node_modules/setprototypeof": {
436
+ "version": "1.2.0",
437
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
438
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
439
+ },
440
+ "node_modules/statuses": {
441
+ "version": "1.5.0",
442
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
443
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
444
+ "engines": {
445
+ "node": ">= 0.6"
446
+ }
447
+ },
448
+ "node_modules/toidentifier": {
449
+ "version": "1.0.1",
450
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
451
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
452
+ "engines": {
453
+ "node": ">=0.6"
454
+ }
455
+ },
456
+ "node_modules/tsscmp": {
457
+ "version": "1.0.6",
458
+ "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
459
+ "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
460
+ "engines": {
461
+ "node": ">=0.6.x"
462
+ }
463
+ },
464
+ "node_modules/type-is": {
465
+ "version": "1.6.18",
466
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
467
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
468
+ "dependencies": {
469
+ "media-typer": "0.3.0",
470
+ "mime-types": "~2.1.24"
471
+ },
472
+ "engines": {
473
+ "node": ">= 0.6"
474
+ }
475
+ },
476
+ "node_modules/vary": {
477
+ "version": "1.1.2",
478
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
479
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
480
+ "engines": {
481
+ "node": ">= 0.8"
482
+ }
483
+ },
484
+ "node_modules/ylru": {
485
+ "version": "1.2.1",
486
+ "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
487
+ "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==",
488
+ "engines": {
489
+ "node": ">= 4.0.0"
490
+ }
491
+ }
492
+ },
493
+ "dependencies": {
494
+ "accepts": {
495
+ "version": "1.3.7",
496
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
497
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
498
+ "requires": {
499
+ "mime-types": "~2.1.24",
500
+ "negotiator": "0.6.2"
501
+ }
502
+ },
503
+ "cache-content-type": {
504
+ "version": "1.0.1",
505
+ "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
506
+ "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
507
+ "requires": {
508
+ "mime-types": "^2.1.18",
509
+ "ylru": "^1.2.0"
510
+ }
511
+ },
512
+ "co": {
513
+ "version": "4.6.0",
514
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
515
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
516
+ },
517
+ "content-disposition": {
518
+ "version": "0.5.3",
519
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
520
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
521
+ "requires": {
522
+ "safe-buffer": "5.1.2"
523
+ }
524
+ },
525
+ "content-type": {
526
+ "version": "1.0.4",
527
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
528
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
529
+ },
530
+ "cookies": {
531
+ "version": "0.8.0",
532
+ "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
533
+ "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
534
+ "requires": {
535
+ "depd": "~2.0.0",
536
+ "keygrip": "~1.1.0"
537
+ }
538
+ },
539
+ "debug": {
540
+ "version": "4.3.3",
541
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
542
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
543
+ "requires": {
544
+ "ms": "2.1.2"
545
+ }
546
+ },
547
+ "deep-equal": {
548
+ "version": "1.0.1",
549
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
550
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
551
+ },
552
+ "delegates": {
553
+ "version": "1.0.0",
554
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
555
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
556
+ },
557
+ "depd": {
558
+ "version": "2.0.0",
559
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
560
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
561
+ },
562
+ "destroy": {
563
+ "version": "1.0.4",
564
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
565
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
566
+ },
567
+ "ee-first": {
568
+ "version": "1.1.1",
569
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
570
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
571
+ },
572
+ "encodeurl": {
573
+ "version": "1.0.2",
574
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
575
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
576
+ },
577
+ "escape-html": {
578
+ "version": "1.0.3",
579
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
580
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
581
+ },
582
+ "fresh": {
583
+ "version": "0.5.2",
584
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
585
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
586
+ },
587
+ "has-symbols": {
588
+ "version": "1.0.2",
589
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
590
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
591
+ },
592
+ "has-tostringtag": {
593
+ "version": "1.0.0",
594
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
595
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
596
+ "requires": {
597
+ "has-symbols": "^1.0.2"
598
+ }
599
+ },
600
+ "http-assert": {
601
+ "version": "1.5.0",
602
+ "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
603
+ "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
604
+ "requires": {
605
+ "deep-equal": "~1.0.1",
606
+ "http-errors": "~1.8.0"
607
+ }
608
+ },
609
+ "http-errors": {
610
+ "version": "1.8.1",
611
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
612
+ "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
613
+ "requires": {
614
+ "depd": "~1.1.2",
615
+ "inherits": "2.0.4",
616
+ "setprototypeof": "1.2.0",
617
+ "statuses": ">= 1.5.0 < 2",
618
+ "toidentifier": "1.0.1"
619
+ },
620
+ "dependencies": {
621
+ "depd": {
622
+ "version": "1.1.2",
623
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
624
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
625
+ }
626
+ }
627
+ },
628
+ "inherits": {
629
+ "version": "2.0.4",
630
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
631
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
632
+ },
633
+ "is-generator-function": {
634
+ "version": "1.0.10",
635
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
636
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
637
+ "requires": {
638
+ "has-tostringtag": "^1.0.0"
639
+ }
640
+ },
641
+ "keygrip": {
642
+ "version": "1.1.0",
643
+ "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
644
+ "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
645
+ "requires": {
646
+ "tsscmp": "1.0.6"
647
+ }
648
+ },
649
+ "koa": {
650
+ "version": "2.13.4",
651
+ "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
652
+ "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==",
653
+ "requires": {
654
+ "accepts": "^1.3.5",
655
+ "cache-content-type": "^1.0.0",
656
+ "content-disposition": "~0.5.2",
657
+ "content-type": "^1.0.4",
658
+ "cookies": "~0.8.0",
659
+ "debug": "^4.3.2",
660
+ "delegates": "^1.0.0",
661
+ "depd": "^2.0.0",
662
+ "destroy": "^1.0.4",
663
+ "encodeurl": "^1.0.2",
664
+ "escape-html": "^1.0.3",
665
+ "fresh": "~0.5.2",
666
+ "http-assert": "^1.3.0",
667
+ "http-errors": "^1.6.3",
668
+ "is-generator-function": "^1.0.7",
669
+ "koa-compose": "^4.1.0",
670
+ "koa-convert": "^2.0.0",
671
+ "on-finished": "^2.3.0",
672
+ "only": "~0.0.2",
673
+ "parseurl": "^1.3.2",
674
+ "statuses": "^1.5.0",
675
+ "type-is": "^1.6.16",
676
+ "vary": "^1.1.2"
677
+ }
678
+ },
679
+ "koa-compose": {
680
+ "version": "4.1.0",
681
+ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
682
+ "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
683
+ },
684
+ "koa-convert": {
685
+ "version": "2.0.0",
686
+ "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
687
+ "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
688
+ "requires": {
689
+ "co": "^4.6.0",
690
+ "koa-compose": "^4.1.0"
691
+ }
692
+ },
693
+ "koa-send": {
694
+ "version": "5.0.1",
695
+ "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
696
+ "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
697
+ "requires": {
698
+ "debug": "^4.1.1",
699
+ "http-errors": "^1.7.3",
700
+ "resolve-path": "^1.4.0"
701
+ }
702
+ },
703
+ "koa-static": {
704
+ "version": "5.0.0",
705
+ "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
706
+ "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
707
+ "requires": {
708
+ "debug": "^3.1.0",
709
+ "koa-send": "^5.0.0"
710
+ },
711
+ "dependencies": {
712
+ "debug": {
713
+ "version": "3.2.7",
714
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
715
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
716
+ "requires": {
717
+ "ms": "^2.1.1"
718
+ }
719
+ }
720
+ }
721
+ },
722
+ "media-typer": {
723
+ "version": "0.3.0",
724
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
725
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
726
+ },
727
+ "mime-db": {
728
+ "version": "1.51.0",
729
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
730
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
731
+ },
732
+ "mime-types": {
733
+ "version": "2.1.34",
734
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
735
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
736
+ "requires": {
737
+ "mime-db": "1.51.0"
738
+ }
739
+ },
740
+ "ms": {
741
+ "version": "2.1.2",
742
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
743
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
744
+ },
745
+ "negotiator": {
746
+ "version": "0.6.2",
747
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
748
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
749
+ },
750
+ "on-finished": {
751
+ "version": "2.3.0",
752
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
753
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
754
+ "requires": {
755
+ "ee-first": "1.1.1"
756
+ }
757
+ },
758
+ "only": {
759
+ "version": "0.0.2",
760
+ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
761
+ "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
762
+ },
763
+ "parseurl": {
764
+ "version": "1.3.3",
765
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
766
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
767
+ },
768
+ "path-is-absolute": {
769
+ "version": "1.0.1",
770
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
771
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
772
+ },
773
+ "resolve-path": {
774
+ "version": "1.4.0",
775
+ "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
776
+ "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
777
+ "requires": {
778
+ "http-errors": "~1.6.2",
779
+ "path-is-absolute": "1.0.1"
780
+ },
781
+ "dependencies": {
782
+ "depd": {
783
+ "version": "1.1.2",
784
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
785
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
786
+ },
787
+ "http-errors": {
788
+ "version": "1.6.3",
789
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
790
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
791
+ "requires": {
792
+ "depd": "~1.1.2",
793
+ "inherits": "2.0.3",
794
+ "setprototypeof": "1.1.0",
795
+ "statuses": ">= 1.4.0 < 2"
796
+ }
797
+ },
798
+ "inherits": {
799
+ "version": "2.0.3",
800
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
801
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
802
+ },
803
+ "setprototypeof": {
804
+ "version": "1.1.0",
805
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
806
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
807
+ }
808
+ }
809
+ },
810
+ "safe-buffer": {
811
+ "version": "5.1.2",
812
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
813
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
814
+ },
815
+ "setprototypeof": {
816
+ "version": "1.2.0",
817
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
818
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
819
+ },
820
+ "statuses": {
821
+ "version": "1.5.0",
822
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
823
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
824
+ },
825
+ "toidentifier": {
826
+ "version": "1.0.1",
827
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
828
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
829
+ },
830
+ "tsscmp": {
831
+ "version": "1.0.6",
832
+ "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
833
+ "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
834
+ },
835
+ "type-is": {
836
+ "version": "1.6.18",
837
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
838
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
839
+ "requires": {
840
+ "media-typer": "0.3.0",
841
+ "mime-types": "~2.1.24"
842
+ }
843
+ },
844
+ "vary": {
845
+ "version": "1.1.2",
846
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
847
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
848
+ },
849
+ "ylru": {
850
+ "version": "1.2.1",
851
+ "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
852
+ "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ=="
853
+ }
854
+ }
855
+}
package.json
new
+9
@@ -0,0 +1,9 @@
1
+{
2
+ "scripts": {
3
+ "start": "node src"
4
+ },
5
+ "dependencies": {
6
+ "koa": "^2.13.4",
7
+ "koa-static": "^5.0.0"
8
+ }
9
+}
src/index.js
new
+19
@@ -0,0 +1,19 @@
1
+const Koa = require('koa')
2
+const serve = require('koa-static')
3
+const srv = new Koa()
4
+
5
+const frontend = serve('frontend')
6
+srv.use((ctx,next) => {
7
+ const rq = ctx.request
8
+ if (rq.method === 'GET' && rq.originalUrl === '/c') {
9
+ ctx.body = 'ciao'
10
+ }
11
+ else
12
+ return frontend(ctx,next)
13
+})
14
+srv.listen(3000)
15
+console.log('running')
16
+/*
17
+body
18
+set(k,v)
19
+* */
\ No newline at end of file