express-ext 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/resources.js +20 -20
- package/lib/search.js +157 -56
- package/package.json +6 -2
- package/src/resources.ts +17 -3
- package/src/search.ts +149 -43
package/lib/resources.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports,
|
|
3
|
-
var fs = require(
|
|
4
|
-
var http = require(
|
|
5
|
-
var https = require(
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var http = require('http');
|
|
5
|
+
var https = require('https');
|
|
6
6
|
var resources = (function () {
|
|
7
|
-
function resources() {
|
|
8
|
-
|
|
7
|
+
function resources() {}
|
|
8
|
+
resources.pageSizes = [12, 24, 60, 100, 120, 180, 300, 600];
|
|
9
|
+
resources.page = 'page';
|
|
10
|
+
resources.limit = 'limit';
|
|
11
|
+
resources.defaultLimit = 12;
|
|
12
|
+
resources.sort = 'sort';
|
|
13
|
+
resources.partial = 'partial';
|
|
9
14
|
resources.encoding = 'utf-8';
|
|
10
15
|
return resources;
|
|
11
|
-
}()
|
|
16
|
+
})();
|
|
12
17
|
exports.resources = resources;
|
|
13
18
|
var TypeChecker = (function () {
|
|
14
19
|
function TypeChecker(attributes, allowUndefined) {
|
|
@@ -20,19 +25,17 @@ var TypeChecker = (function () {
|
|
|
20
25
|
var obj = req.body;
|
|
21
26
|
if (!obj || obj === '') {
|
|
22
27
|
res.status(400).end('The request body cannot be empty');
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
28
|
+
} else {
|
|
25
29
|
var errors = resources.check(obj, this.attributes, this.allowUndefined);
|
|
26
30
|
if (errors.length > 0) {
|
|
27
31
|
res.status(400).json(errors).end();
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
32
|
+
} else {
|
|
30
33
|
next();
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
};
|
|
34
37
|
return TypeChecker;
|
|
35
|
-
}()
|
|
38
|
+
})();
|
|
36
39
|
exports.TypeChecker = TypeChecker;
|
|
37
40
|
function check(attributes, allowUndefined) {
|
|
38
41
|
var x = new TypeChecker(attributes, allowUndefined);
|
|
@@ -64,23 +67,20 @@ function start(a, s) {
|
|
|
64
67
|
https.createServer(s.options, a).listen(s.port, function () {
|
|
65
68
|
console.log('Use https and start server at port ' + s.port);
|
|
66
69
|
});
|
|
67
|
-
}
|
|
68
|
-
else if (s.key && s.cert && s.key.length > 0 && s.cert.length > 0) {
|
|
70
|
+
} else if (s.key && s.cert && s.key.length > 0 && s.cert.length > 0) {
|
|
69
71
|
var options = {
|
|
70
72
|
key: fs.readFileSync(s.key),
|
|
71
|
-
cert: fs.readFileSync(s.cert)
|
|
73
|
+
cert: fs.readFileSync(s.cert),
|
|
72
74
|
};
|
|
73
75
|
https.createServer(options, a).listen(s.port, function () {
|
|
74
76
|
console.log('Use https and start server at port ' + s.port);
|
|
75
77
|
});
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
+
} else {
|
|
78
79
|
http.createServer(a).listen(s.port, function () {
|
|
79
80
|
console.log('Start server at port ' + s.port);
|
|
80
81
|
});
|
|
81
82
|
}
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
83
|
+
} else {
|
|
84
84
|
http.createServer(a).listen(s.port, function () {
|
|
85
85
|
console.log('Start server at port ' + s.port);
|
|
86
86
|
});
|
package/lib/search.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
3
|
var http_1 = require('./http');
|
|
4
|
+
var resources_1 = require('./resources');
|
|
5
|
+
var et = '';
|
|
4
6
|
function getOffset(limit, page) {
|
|
5
7
|
var offset = limit * (page - 1);
|
|
6
8
|
return offset < 0 ? 0 : offset;
|
|
@@ -32,68 +34,167 @@ function buildPages(pageSize, total) {
|
|
|
32
34
|
return arr;
|
|
33
35
|
}
|
|
34
36
|
exports.buildPages = buildPages;
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
function hasSearch(req) {
|
|
38
|
+
return req.url.indexOf('?') >= 0;
|
|
39
|
+
}
|
|
40
|
+
exports.hasSearch = hasSearch;
|
|
41
|
+
function getSearch(url) {
|
|
42
|
+
var i = url.indexOf('?');
|
|
43
|
+
return i < 0 ? et : url.substring(i + 1);
|
|
44
|
+
}
|
|
45
|
+
exports.getSearch = getSearch;
|
|
46
|
+
function getField(search, fieldName) {
|
|
47
|
+
var i = search.indexOf(fieldName + '=');
|
|
38
48
|
if (i < 0) {
|
|
39
49
|
return '';
|
|
40
50
|
}
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
if (i > 0) {
|
|
52
|
+
if (search.substring(i - 1, 1) != '&') {
|
|
53
|
+
i = search.indexOf('&' + fieldName + '=');
|
|
54
|
+
if (i < 0) {
|
|
55
|
+
return search;
|
|
56
|
+
}
|
|
57
|
+
i = i + 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
var j = search.indexOf('&', i + fieldName.length);
|
|
61
|
+
return j >= 0 ? search.substring(i, j) : search.substring(i);
|
|
43
62
|
}
|
|
44
|
-
exports.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
return
|
|
63
|
+
exports.getField = getField;
|
|
64
|
+
function removeField(search, fieldName) {
|
|
65
|
+
var i = search.indexOf(fieldName + '=');
|
|
66
|
+
if (i < 0) {
|
|
67
|
+
return search;
|
|
49
68
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
var q2 = query.indexOf(p2);
|
|
58
|
-
if (q2 >= 0) {
|
|
59
|
-
query = query.substring(0, q1) + query.substring(q1 + partialTrue.length + 2);
|
|
69
|
+
if (i > 0) {
|
|
70
|
+
if (search.substring(i - 1, 1) != '&') {
|
|
71
|
+
i = search.indexOf('&' + fieldName + '=');
|
|
72
|
+
if (i < 0) {
|
|
73
|
+
return search;
|
|
74
|
+
}
|
|
75
|
+
i = i + 1;
|
|
60
76
|
}
|
|
61
77
|
}
|
|
62
|
-
var
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
var j = search.indexOf('&', i + fieldName.length);
|
|
79
|
+
return j >= 0 ? search.substring(0, i) + search.substring(j + 1) : search.substring(0, i - 1);
|
|
80
|
+
}
|
|
81
|
+
exports.removeField = removeField;
|
|
82
|
+
function removePage(search) {
|
|
83
|
+
search = removeField(search, resources_1.resources.page);
|
|
84
|
+
search = removeField(search, resources_1.resources.partial);
|
|
85
|
+
return search;
|
|
86
|
+
}
|
|
87
|
+
exports.removePage = removePage;
|
|
88
|
+
function buildPageSearch(search) {
|
|
89
|
+
var sr = removePage(search);
|
|
90
|
+
return sr.length == 0 ? sr : '&' + sr;
|
|
91
|
+
}
|
|
92
|
+
exports.buildPageSearch = buildPageSearch;
|
|
93
|
+
function buildPageSearchFromUrl(url) {
|
|
94
|
+
var search = getSearch(url);
|
|
95
|
+
return buildPageSearch(search);
|
|
96
|
+
}
|
|
97
|
+
exports.buildPageSearchFromUrl = buildPageSearchFromUrl;
|
|
98
|
+
function removeSort(search) {
|
|
99
|
+
search = removeField(search, resources_1.resources.sort);
|
|
100
|
+
search = removeField(search, resources_1.resources.partial);
|
|
101
|
+
return search;
|
|
102
|
+
}
|
|
103
|
+
exports.removeSort = removeSort;
|
|
104
|
+
function getSortString(field, sort) {
|
|
105
|
+
if (field === sort.field) {
|
|
106
|
+
return sort.type === '-' ? field : '-' + field;
|
|
107
|
+
}
|
|
108
|
+
return field;
|
|
109
|
+
}
|
|
110
|
+
exports.getSortString = getSortString;
|
|
111
|
+
function buildSort(s) {
|
|
112
|
+
if (!s || s.indexOf(',') >= 0) {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
if (s.startsWith('-')) {
|
|
116
|
+
return { field: s.substring(1), type: '-' };
|
|
65
117
|
} else {
|
|
66
|
-
|
|
67
|
-
if (query.indexOf(x) >= 0) {
|
|
68
|
-
return query.replace(x, '');
|
|
69
|
-
}
|
|
70
|
-
var x2 = '&' + pageQuery;
|
|
71
|
-
if (query.indexOf(x2) >= 0) {
|
|
72
|
-
return query.replace(x2, '');
|
|
73
|
-
}
|
|
74
|
-
return query.replace(pageQuery, '');
|
|
118
|
+
return { field: s.startsWith('+') ? s.substring(1) : s, type: '+' };
|
|
75
119
|
}
|
|
76
120
|
}
|
|
77
|
-
exports.
|
|
78
|
-
function
|
|
79
|
-
|
|
121
|
+
exports.buildSort = buildSort;
|
|
122
|
+
function buildSortFromRequest(req) {
|
|
123
|
+
var s = http_1.query(req, resources_1.resources.sort);
|
|
124
|
+
return buildSort(s);
|
|
80
125
|
}
|
|
81
|
-
exports.
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
126
|
+
exports.buildSortFromRequest = buildSortFromRequest;
|
|
127
|
+
function renderSort(field, sort) {
|
|
128
|
+
if (field === sort.field) {
|
|
129
|
+
return sort.type === '-' ? "<i class='sort-down'></i>" : "<i class='sort-up'></i>";
|
|
130
|
+
}
|
|
131
|
+
return et;
|
|
85
132
|
}
|
|
86
|
-
exports.
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
133
|
+
exports.renderSort = renderSort;
|
|
134
|
+
function buildSortSearch(search, fields, sort) {
|
|
135
|
+
search = removeSort(search);
|
|
136
|
+
var sorts = {};
|
|
137
|
+
var prefix = search.length > 0 ? '?' + search + '&' : '?';
|
|
138
|
+
for (var i = 0; i < fields.length; i++) {
|
|
139
|
+
sorts[fields[i]] = {
|
|
140
|
+
url: prefix + resources_1.resources.sort + '=' + getSortString(fields[i], sort),
|
|
141
|
+
tag: renderSort(fields[i], sort),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return sorts;
|
|
90
145
|
}
|
|
91
|
-
exports.
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
|
|
146
|
+
exports.buildSortSearch = buildSortSearch;
|
|
147
|
+
function clone(obj) {
|
|
148
|
+
if (!obj) {
|
|
149
|
+
return obj;
|
|
150
|
+
}
|
|
151
|
+
if (obj instanceof Date) {
|
|
152
|
+
return new Date(obj.getTime());
|
|
153
|
+
}
|
|
154
|
+
if (typeof obj !== 'object') {
|
|
155
|
+
return obj;
|
|
156
|
+
}
|
|
157
|
+
if (Array.isArray(obj)) {
|
|
158
|
+
var arr = [];
|
|
159
|
+
for (var _i = 0, obj_1 = obj; _i < obj_1.length; _i++) {
|
|
160
|
+
var sub = obj_1[_i];
|
|
161
|
+
var c = clone(sub);
|
|
162
|
+
arr.push(c);
|
|
163
|
+
}
|
|
164
|
+
return arr;
|
|
165
|
+
}
|
|
166
|
+
var x = {};
|
|
167
|
+
var keys = Object.keys(obj);
|
|
168
|
+
for (var _a = 0, keys_1 = keys; _a < keys_1.length; _a++) {
|
|
169
|
+
var k = keys_1[_a];
|
|
170
|
+
var v = obj[k];
|
|
171
|
+
if (v instanceof Date) {
|
|
172
|
+
x[k] = new Date(v.getTime());
|
|
173
|
+
} else {
|
|
174
|
+
switch (typeof v) {
|
|
175
|
+
case 'object':
|
|
176
|
+
x[k] = clone(v);
|
|
177
|
+
break;
|
|
178
|
+
default:
|
|
179
|
+
x[k] = v;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return x;
|
|
185
|
+
}
|
|
186
|
+
exports.clone = clone;
|
|
187
|
+
function cloneFilter(obj, page, limit) {
|
|
188
|
+
var f = clone(obj);
|
|
189
|
+
if (!obj.hasOwnProperty(resources_1.resources.page)) {
|
|
190
|
+
obj[resources_1.resources.page] = page;
|
|
191
|
+
}
|
|
192
|
+
if (!obj.hasOwnProperty(resources_1.resources.limit)) {
|
|
193
|
+
obj[resources_1.resources.limit] = limit;
|
|
194
|
+
}
|
|
195
|
+
return f;
|
|
95
196
|
}
|
|
96
|
-
exports.
|
|
197
|
+
exports.cloneFilter = cloneFilter;
|
|
97
198
|
function jsonResult(res, result, quick, fields, config) {
|
|
98
199
|
if (quick && fields && fields.length > 0) {
|
|
99
200
|
res.status(200).json(toCsv(fields, result)).end();
|
|
@@ -205,8 +306,8 @@ function fromUrl(req, arr) {
|
|
|
205
306
|
var s = {};
|
|
206
307
|
var obj = req.query;
|
|
207
308
|
var keys = Object.keys(obj);
|
|
208
|
-
for (var _i = 0,
|
|
209
|
-
var key =
|
|
309
|
+
for (var _i = 0, keys_2 = keys; _i < keys_2.length; _i++) {
|
|
310
|
+
var key = keys_2[_i];
|
|
210
311
|
if (inArray(key, arr)) {
|
|
211
312
|
var x = obj[key].split(',');
|
|
212
313
|
setValue(s, key, x);
|
|
@@ -495,8 +596,8 @@ function buildMetadata(attributes, includeDate) {
|
|
|
495
596
|
var keys = Object.keys(attributes);
|
|
496
597
|
var dates = [];
|
|
497
598
|
var numbers = [];
|
|
498
|
-
for (var _i = 0,
|
|
499
|
-
var key =
|
|
599
|
+
for (var _i = 0, keys_3 = keys; _i < keys_3.length; _i++) {
|
|
600
|
+
var key = keys_3[_i];
|
|
500
601
|
var attr = attributes[key];
|
|
501
602
|
if (attr.type === 'number' || attr.type === 'integer') {
|
|
502
603
|
numbers.push(key);
|
|
@@ -564,8 +665,8 @@ function format(obj, dates, nums) {
|
|
|
564
665
|
}
|
|
565
666
|
} else if (typeof v === 'object') {
|
|
566
667
|
var keys = Object.keys(v);
|
|
567
|
-
for (var _a = 0,
|
|
568
|
-
var key =
|
|
668
|
+
for (var _a = 0, keys_4 = keys; _a < keys_4.length; _a++) {
|
|
669
|
+
var key = keys_4[_a];
|
|
569
670
|
var v2 = v[key];
|
|
570
671
|
if (v2 instanceof Date) {
|
|
571
672
|
continue;
|
|
@@ -607,8 +708,8 @@ function format(obj, dates, nums) {
|
|
|
607
708
|
}
|
|
608
709
|
} else if (typeof v === 'object') {
|
|
609
710
|
var keys = Object.keys(v);
|
|
610
|
-
for (var _c = 0,
|
|
611
|
-
var key =
|
|
711
|
+
for (var _c = 0, keys_5 = keys; _c < keys_5.length; _c++) {
|
|
712
|
+
var key = keys_5[_c];
|
|
612
713
|
var v2 = v[key];
|
|
613
714
|
if (v2 instanceof Date) {
|
|
614
715
|
delete o[key];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-ext",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "express-ext",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"express",
|
|
28
|
+
"express-plus",
|
|
29
|
+
"express plus",
|
|
28
30
|
"express-ext",
|
|
29
|
-
"express
|
|
31
|
+
"express ext",
|
|
32
|
+
"express-extension",
|
|
33
|
+
"express extension"
|
|
30
34
|
]
|
|
31
35
|
}
|
package/src/resources.ts
CHANGED
|
@@ -4,15 +4,24 @@ import * as http from 'http';
|
|
|
4
4
|
import * as https from 'https';
|
|
5
5
|
import { Attributes, ErrorMessage } from './metadata';
|
|
6
6
|
|
|
7
|
+
export interface StringMap {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
}
|
|
7
10
|
// tslint:disable-next-line:class-name
|
|
8
11
|
export class resources {
|
|
12
|
+
static pageSizes = [12, 24, 60, 100, 120, 180, 300, 600];
|
|
13
|
+
static page = 'page';
|
|
14
|
+
static limit = 'limit';
|
|
15
|
+
static defaultLimit = 12;
|
|
16
|
+
static sort = 'sort';
|
|
17
|
+
static partial = 'partial';
|
|
9
18
|
static createValidator?: <T>(attributes: Attributes, allowUndefined?: boolean, max?: number) => Validator<T>;
|
|
10
19
|
static check: (obj: any, attributes: Attributes, allowUndefined?: boolean, patch?: boolean) => ErrorMessage[];
|
|
11
20
|
static encoding?: BufferEncoding = 'utf-8';
|
|
12
21
|
}
|
|
13
22
|
|
|
14
23
|
export interface Validator<T> {
|
|
15
|
-
validate(obj: T, patch?: boolean): Promise<ErrorMessage[]>;
|
|
24
|
+
validate(obj: T, patch?: boolean, resource?: StringMap): Promise<ErrorMessage[]>;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
// tslint:disable-next-line:max-classes-per-file
|
|
@@ -64,7 +73,12 @@ export interface TemplateNode {
|
|
|
64
73
|
suffix?: string | null;
|
|
65
74
|
prefix?: string | null;
|
|
66
75
|
}
|
|
67
|
-
export function loadTemplates(
|
|
76
|
+
export function loadTemplates(
|
|
77
|
+
ok: boolean | undefined,
|
|
78
|
+
buildTemplates: (streams: string[], correct?: (stream: string) => string) => Map<string, Template>,
|
|
79
|
+
correct?: (stream: string) => string,
|
|
80
|
+
files?: string[],
|
|
81
|
+
): Map<string, Template> | undefined {
|
|
68
82
|
if (!ok) {
|
|
69
83
|
return undefined;
|
|
70
84
|
}
|
|
@@ -97,7 +111,7 @@ export function start(a: Application, s: Server): void {
|
|
|
97
111
|
} else if (s.key && s.cert && s.key.length > 0 && s.cert.length > 0) {
|
|
98
112
|
const options = {
|
|
99
113
|
key: fs.readFileSync(s.key),
|
|
100
|
-
cert: fs.readFileSync(s.cert)
|
|
114
|
+
cert: fs.readFileSync(s.cert),
|
|
101
115
|
};
|
|
102
116
|
https.createServer(options, a).listen(s.port, () => {
|
|
103
117
|
console.log('Use https and start server at port ' + s.port);
|
package/src/search.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
|
-
import { minimizeArray } from './http';
|
|
2
|
+
import { minimizeArray, query } from './http';
|
|
3
3
|
import { Attribute, Attributes } from './metadata';
|
|
4
|
+
import { resources } from './resources';
|
|
5
|
+
|
|
6
|
+
const et = '';
|
|
4
7
|
|
|
5
8
|
export interface Filter {
|
|
9
|
+
page?: number;
|
|
10
|
+
limit?: number;
|
|
11
|
+
|
|
6
12
|
fields?: string[];
|
|
7
13
|
sort?: string;
|
|
8
14
|
|
|
@@ -58,61 +64,161 @@ export function buildPages(pageSize?: number, total?: number): number[] {
|
|
|
58
64
|
}
|
|
59
65
|
return arr;
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
|
|
68
|
+
export function hasSearch(req: Request): boolean {
|
|
69
|
+
return req.url.indexOf('?') >= 0;
|
|
70
|
+
}
|
|
71
|
+
export function getSearch(url: string): string {
|
|
72
|
+
const i = url.indexOf('?');
|
|
73
|
+
return i < 0 ? et : url.substring(i + 1);
|
|
74
|
+
}
|
|
75
|
+
export function getField(search: string, fieldName: string): string {
|
|
76
|
+
let i = search.indexOf(fieldName + '=');
|
|
64
77
|
if (i < 0) {
|
|
65
78
|
return '';
|
|
66
79
|
}
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
if (i > 0) {
|
|
81
|
+
if (search.substring(i - 1, 1) != '&') {
|
|
82
|
+
i = search.indexOf('&' + fieldName + '=');
|
|
83
|
+
if (i < 0) {
|
|
84
|
+
return search;
|
|
85
|
+
}
|
|
86
|
+
i = i + 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const j = search.indexOf('&', i + fieldName.length);
|
|
90
|
+
return j >= 0 ? search.substring(i, j) : search.substring(i);
|
|
69
91
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
return
|
|
92
|
+
export function removeField(search: string, fieldName: string): string {
|
|
93
|
+
let i = search.indexOf(fieldName + '=');
|
|
94
|
+
if (i < 0) {
|
|
95
|
+
return search;
|
|
74
96
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const q2 = query.indexOf(p2);
|
|
83
|
-
if (q2 >= 0) {
|
|
84
|
-
query = query.substring(0, q1) + query.substring(q1 + partialTrue.length + 2);
|
|
97
|
+
if (i > 0) {
|
|
98
|
+
if (search.substring(i - 1, 1) != '&') {
|
|
99
|
+
i = search.indexOf('&' + fieldName + '=');
|
|
100
|
+
if (i < 0) {
|
|
101
|
+
return search;
|
|
102
|
+
}
|
|
103
|
+
i = i + 1;
|
|
85
104
|
}
|
|
86
105
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
106
|
+
const j = search.indexOf('&', i + fieldName.length);
|
|
107
|
+
return j >= 0 ? search.substring(0, i) + search.substring(j + 1) : search.substring(0, i - 1);
|
|
108
|
+
}
|
|
109
|
+
export function removePage(search: string): string {
|
|
110
|
+
search = removeField(search, resources.page);
|
|
111
|
+
search = removeField(search, resources.partial);
|
|
112
|
+
return search;
|
|
113
|
+
}
|
|
114
|
+
export function buildPageSearch(search: string): string {
|
|
115
|
+
const sr = removePage(search);
|
|
116
|
+
return sr.length == 0 ? sr : '&' + sr;
|
|
117
|
+
}
|
|
118
|
+
export function buildPageSearchFromUrl(url: string): string {
|
|
119
|
+
const search = getSearch(url);
|
|
120
|
+
return buildPageSearch(search);
|
|
121
|
+
}
|
|
122
|
+
export function removeSort(search: string): string {
|
|
123
|
+
search = removeField(search, resources.sort);
|
|
124
|
+
search = removeField(search, resources.partial);
|
|
125
|
+
return search;
|
|
126
|
+
}
|
|
127
|
+
export interface Sort {
|
|
128
|
+
field?: string;
|
|
129
|
+
type?: string;
|
|
130
|
+
}
|
|
131
|
+
export interface SortType {
|
|
132
|
+
url: string;
|
|
133
|
+
tag: string;
|
|
134
|
+
}
|
|
135
|
+
export interface SortMap {
|
|
136
|
+
[key: string]: SortType;
|
|
137
|
+
}
|
|
138
|
+
export function getSortString(field: string, sort: Sort): string {
|
|
139
|
+
if (field === sort.field) {
|
|
140
|
+
return sort.type === '-' ? field : '-' + field;
|
|
141
|
+
}
|
|
142
|
+
return field;
|
|
143
|
+
}
|
|
144
|
+
export function buildSort(s?: string): Sort {
|
|
145
|
+
if (!s || s.indexOf(',') >= 0) {
|
|
146
|
+
return {} as Sort;
|
|
147
|
+
}
|
|
148
|
+
if (s.startsWith('-')) {
|
|
149
|
+
return { field: s.substring(1), type: '-' };
|
|
90
150
|
} else {
|
|
91
|
-
|
|
92
|
-
if (query.indexOf(x) >= 0) {
|
|
93
|
-
return query.replace(x, '');
|
|
94
|
-
}
|
|
95
|
-
const x2 = '&' + pageQuery;
|
|
96
|
-
if (query.indexOf(x2) >= 0) {
|
|
97
|
-
return query.replace(x2, '');
|
|
98
|
-
}
|
|
99
|
-
return query.replace(pageQuery, '');
|
|
151
|
+
return { field: s.startsWith('+') ? s.substring(1) : s, type: '+' };
|
|
100
152
|
}
|
|
101
153
|
}
|
|
102
|
-
export function
|
|
103
|
-
|
|
154
|
+
export function buildSortFromRequest(req: Request): Sort {
|
|
155
|
+
const s = query(req, resources.sort);
|
|
156
|
+
return buildSort(s);
|
|
104
157
|
}
|
|
105
|
-
export function
|
|
106
|
-
|
|
107
|
-
|
|
158
|
+
export function renderSort(field: string, sort: Sort): string {
|
|
159
|
+
if (field === sort.field) {
|
|
160
|
+
return sort.type === '-' ? "<i class='sort-down'></i>" : "<i class='sort-up'></i>";
|
|
161
|
+
}
|
|
162
|
+
return et;
|
|
163
|
+
}
|
|
164
|
+
export function buildSortSearch(search: string, fields: string[], sort: Sort): SortMap {
|
|
165
|
+
search = removeSort(search);
|
|
166
|
+
let sorts: SortMap = {};
|
|
167
|
+
const prefix = search.length > 0 ? '?' + search + '&' : '?';
|
|
168
|
+
for (let i = 0; i < fields.length; i++) {
|
|
169
|
+
sorts[fields[i]] = {
|
|
170
|
+
url: prefix + resources.sort + '=' + getSortString(fields[i], sort),
|
|
171
|
+
tag: renderSort(fields[i], sort),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return sorts;
|
|
108
175
|
}
|
|
109
|
-
export function
|
|
110
|
-
|
|
111
|
-
|
|
176
|
+
export function clone(obj: any): any {
|
|
177
|
+
if (!obj) {
|
|
178
|
+
return obj;
|
|
179
|
+
}
|
|
180
|
+
if (obj instanceof Date) {
|
|
181
|
+
return new Date(obj.getTime());
|
|
182
|
+
}
|
|
183
|
+
if (typeof obj !== 'object') {
|
|
184
|
+
return obj;
|
|
185
|
+
}
|
|
186
|
+
if (Array.isArray(obj)) {
|
|
187
|
+
const arr = [];
|
|
188
|
+
for (const sub of obj) {
|
|
189
|
+
const c = clone(sub);
|
|
190
|
+
arr.push(c);
|
|
191
|
+
}
|
|
192
|
+
return arr;
|
|
193
|
+
}
|
|
194
|
+
const x: any = {};
|
|
195
|
+
const keys = Object.keys(obj);
|
|
196
|
+
for (const k of keys) {
|
|
197
|
+
const v = obj[k];
|
|
198
|
+
if (v instanceof Date) {
|
|
199
|
+
x[k] = new Date(v.getTime());
|
|
200
|
+
} else {
|
|
201
|
+
switch (typeof v) {
|
|
202
|
+
case 'object':
|
|
203
|
+
x[k] = clone(v);
|
|
204
|
+
break;
|
|
205
|
+
default:
|
|
206
|
+
x[k] = v;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return x;
|
|
112
212
|
}
|
|
113
|
-
export function
|
|
114
|
-
const
|
|
115
|
-
|
|
213
|
+
export function cloneFilter<F extends Filter>(obj: F, page: number, limit: number): F {
|
|
214
|
+
const f = clone(obj);
|
|
215
|
+
if (!obj.hasOwnProperty(resources.page)) {
|
|
216
|
+
(obj as any)[resources.page] = page;
|
|
217
|
+
}
|
|
218
|
+
if (!obj.hasOwnProperty(resources.limit)) {
|
|
219
|
+
(obj as any)[resources.limit] = limit;
|
|
220
|
+
}
|
|
221
|
+
return f;
|
|
116
222
|
}
|
|
117
223
|
|
|
118
224
|
export function jsonResult<T>(res: Response, result: SearchResult<T>, quick?: boolean, fields?: string[], config?: SearchConfig): void {
|