@unito/integration-sdk 1.8.5 → 2.0.1
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/dist/src/handler.js +1 -0
- package/dist/src/index.cjs +14 -1
- package/dist/src/integration.js +2 -0
- package/dist/src/middlewares/filters.js +2 -2
- package/dist/src/middlewares/search.d.ts +10 -0
- package/dist/src/middlewares/search.js +11 -0
- package/dist/src/resources/context.d.ts +10 -0
- package/dist/test/helpers.test.js +14 -14
- package/dist/test/middlewares/filters.test.js +4 -4
- package/dist/test/middlewares/search.test.d.ts +1 -0
- package/dist/test/middlewares/search.test.js +21 -0
- package/package.json +10 -4
- package/src/handler.ts +1 -0
- package/src/integration.ts +2 -0
- package/src/middlewares/filters.ts +2 -2
- package/src/middlewares/search.ts +31 -0
- package/src/resources/context.ts +10 -0
- package/test/helpers.test.ts +14 -14
- package/test/middlewares/filters.test.ts +4 -4
- package/test/middlewares/search.test.ts +34 -0
package/dist/src/handler.js
CHANGED
package/dist/src/index.cjs
CHANGED
|
@@ -523,6 +523,7 @@ class Handler {
|
|
|
523
523
|
const collection = await handler({
|
|
524
524
|
credentials: res.locals.credentials,
|
|
525
525
|
secrets: res.locals.secrets,
|
|
526
|
+
search: res.locals.search,
|
|
526
527
|
selects: res.locals.selects,
|
|
527
528
|
filters: res.locals.filters,
|
|
528
529
|
logger: res.locals.logger,
|
|
@@ -828,7 +829,7 @@ function onError(err, _req, res, next) {
|
|
|
828
829
|
// a subset of the symbol of another operator.
|
|
829
830
|
//
|
|
830
831
|
// For example, the symbol "=" (EQUAL) is a subset of the symbol "!=" (NOT_EQUAL).
|
|
831
|
-
const ORDERED_OPERATORS = Object.values(integrationApi.
|
|
832
|
+
const ORDERED_OPERATORS = Object.values(integrationApi.OperatorTypes).sort((o1, o2) => o2.length - o1.length);
|
|
832
833
|
function extractFilters(req, res, next) {
|
|
833
834
|
const rawFilters = req.query.filter;
|
|
834
835
|
res.locals.filters = [];
|
|
@@ -929,6 +930,17 @@ function extractSecrets(req, res, next) {
|
|
|
929
930
|
next();
|
|
930
931
|
}
|
|
931
932
|
|
|
933
|
+
function extractSearch(req, res, next) {
|
|
934
|
+
const rawSearch = req.query.search;
|
|
935
|
+
if (typeof rawSearch === 'string') {
|
|
936
|
+
res.locals.search = rawSearch;
|
|
937
|
+
}
|
|
938
|
+
else {
|
|
939
|
+
res.locals.search = null;
|
|
940
|
+
}
|
|
941
|
+
next();
|
|
942
|
+
}
|
|
943
|
+
|
|
932
944
|
function extractSelects(req, res, next) {
|
|
933
945
|
const rawSelect = req.query.select;
|
|
934
946
|
if (typeof rawSelect === 'string') {
|
|
@@ -1081,6 +1093,7 @@ class Integration {
|
|
|
1081
1093
|
app.use(extractCredentials);
|
|
1082
1094
|
app.use(extractSecrets);
|
|
1083
1095
|
app.use(extractFilters);
|
|
1096
|
+
app.use(extractSearch);
|
|
1084
1097
|
app.use(extractSelects);
|
|
1085
1098
|
app.use(extractRelations);
|
|
1086
1099
|
app.use(extractOperationDeadline);
|
package/dist/src/integration.js
CHANGED
|
@@ -10,6 +10,7 @@ import notFoundMiddleware from './middlewares/notFound.js';
|
|
|
10
10
|
import loggerMiddleware from './middlewares/logger.js';
|
|
11
11
|
import startMiddleware from './middlewares/start.js';
|
|
12
12
|
import secretsMiddleware from './middlewares/secrets.js';
|
|
13
|
+
import searchMiddleware from './middlewares/search.js';
|
|
13
14
|
import selectsMiddleware from './middlewares/selects.js';
|
|
14
15
|
import relationsMiddleware from './middlewares/relations.js';
|
|
15
16
|
import signalMiddleware from './middlewares/signal.js';
|
|
@@ -131,6 +132,7 @@ export default class Integration {
|
|
|
131
132
|
app.use(credentialsMiddleware);
|
|
132
133
|
app.use(secretsMiddleware);
|
|
133
134
|
app.use(filtersMiddleware);
|
|
135
|
+
app.use(searchMiddleware);
|
|
134
136
|
app.use(selectsMiddleware);
|
|
135
137
|
app.use(relationsMiddleware);
|
|
136
138
|
app.use(signalMiddleware);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OperatorTypes } from '@unito/integration-api';
|
|
2
2
|
// The operators are ordered by their symbol length, in descending order.
|
|
3
3
|
// This is necessary because the symbol of an operator can be
|
|
4
4
|
// a subset of the symbol of another operator.
|
|
5
5
|
//
|
|
6
6
|
// For example, the symbol "=" (EQUAL) is a subset of the symbol "!=" (NOT_EQUAL).
|
|
7
|
-
const ORDERED_OPERATORS = Object.values(
|
|
7
|
+
const ORDERED_OPERATORS = Object.values(OperatorTypes).sort((o1, o2) => o2.length - o1.length);
|
|
8
8
|
function extractFilters(req, res, next) {
|
|
9
9
|
const rawFilters = req.query.filter;
|
|
10
10
|
res.locals.filters = [];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
declare global {
|
|
3
|
+
namespace Express {
|
|
4
|
+
interface Locals {
|
|
5
|
+
search: string | null;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
declare function extractSearch(req: Request, res: Response, next: NextFunction): void;
|
|
10
|
+
export default extractSearch;
|
|
@@ -90,6 +90,16 @@ export type GetCollectionContext<P extends Maybe<Params> = Empty, Q extends Quer
|
|
|
90
90
|
* @see {@link Filter}
|
|
91
91
|
*/
|
|
92
92
|
filters: Filter[];
|
|
93
|
+
/**
|
|
94
|
+
* Parsed search query param yielding a free-text search query.
|
|
95
|
+
*
|
|
96
|
+
* Given a search query param:
|
|
97
|
+
* `search=John`
|
|
98
|
+
*
|
|
99
|
+
* Context.search will be:
|
|
100
|
+
* 'John'
|
|
101
|
+
*/
|
|
102
|
+
search: string | null;
|
|
93
103
|
/**
|
|
94
104
|
* Parsed select query param yielding a list of fields to select.
|
|
95
105
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldValueTypes, OperatorTypes, Semantics } from '@unito/integration-api';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { describe, it } from 'node:test';
|
|
4
4
|
import { getApplicableFilters } from '../src/helpers.js';
|
|
@@ -7,48 +7,48 @@ describe('Helpers', () => {
|
|
|
7
7
|
it('returns only filters for defined fields', () => {
|
|
8
8
|
const actual = getApplicableFilters({
|
|
9
9
|
filters: [
|
|
10
|
-
{ field: 'status', operator:
|
|
11
|
-
{ field: 'email', operator:
|
|
10
|
+
{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] },
|
|
11
|
+
{ field: 'email', operator: OperatorTypes.IS_NOT_NULL, values: [] },
|
|
12
12
|
],
|
|
13
13
|
}, [
|
|
14
14
|
{
|
|
15
15
|
name: 'status',
|
|
16
16
|
label: 'Status',
|
|
17
|
-
type:
|
|
17
|
+
type: FieldValueTypes.STRING,
|
|
18
18
|
},
|
|
19
19
|
]);
|
|
20
|
-
const expected = [{ field: 'status', operator:
|
|
20
|
+
const expected = [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] }];
|
|
21
21
|
assert.deepEqual(actual, expected);
|
|
22
22
|
});
|
|
23
23
|
it('translates semantics into field names', () => {
|
|
24
24
|
const actual = getApplicableFilters({
|
|
25
25
|
filters: [
|
|
26
|
-
{ field: 'semantic:displayName', operator:
|
|
27
|
-
{ field: 'semantic:createdAt', operator:
|
|
26
|
+
{ field: 'semantic:displayName', operator: OperatorTypes.START_WITH, values: ['Bob'] },
|
|
27
|
+
{ field: 'semantic:createdAt', operator: OperatorTypes.EQUAL, values: ['2021-01-01'] },
|
|
28
28
|
],
|
|
29
29
|
}, [
|
|
30
30
|
{
|
|
31
31
|
name: 'name',
|
|
32
32
|
label: 'Name',
|
|
33
|
-
type:
|
|
34
|
-
semantic:
|
|
33
|
+
type: FieldValueTypes.STRING,
|
|
34
|
+
semantic: Semantics.DISPLAY_NAME,
|
|
35
35
|
},
|
|
36
36
|
]);
|
|
37
|
-
const expected = [{ field: 'name', operator:
|
|
37
|
+
const expected = [{ field: 'name', operator: OperatorTypes.START_WITH, values: ['Bob'] }];
|
|
38
38
|
assert.deepEqual(actual, expected);
|
|
39
39
|
});
|
|
40
40
|
it('gracefully handle garbage', () => {
|
|
41
41
|
const actual = getApplicableFilters({
|
|
42
42
|
filters: [
|
|
43
|
-
{ field: '...', operator:
|
|
44
|
-
{ field: ':', operator:
|
|
45
|
-
{ field: '', operator:
|
|
43
|
+
{ field: '...', operator: OperatorTypes.EQUAL, values: [] },
|
|
44
|
+
{ field: ':', operator: OperatorTypes.EQUAL, values: [] },
|
|
45
|
+
{ field: '', operator: OperatorTypes.EQUAL, values: [] },
|
|
46
46
|
],
|
|
47
47
|
}, [
|
|
48
48
|
{
|
|
49
49
|
name: 'status',
|
|
50
50
|
label: 'Status',
|
|
51
|
-
type:
|
|
51
|
+
type: FieldValueTypes.STRING,
|
|
52
52
|
},
|
|
53
53
|
]);
|
|
54
54
|
assert.deepEqual(actual, []);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OperatorTypes } from '@unito/integration-api';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { describe, it } from 'node:test';
|
|
4
4
|
import extractFilters from '../../src/middlewares/filters.js';
|
|
5
5
|
describe('filters middleware', () => {
|
|
6
6
|
it('properly parse operators', () => {
|
|
7
|
-
Object.values(
|
|
7
|
+
Object.values(OperatorTypes).forEach(operator => {
|
|
8
8
|
const request = {
|
|
9
9
|
query: { filter: `aKey${operator}value` },
|
|
10
10
|
};
|
|
@@ -20,7 +20,7 @@ describe('filters middleware', () => {
|
|
|
20
20
|
const response = { locals: {} };
|
|
21
21
|
extractFilters(request, response, () => { });
|
|
22
22
|
assert.deepEqual(response.locals, {
|
|
23
|
-
filters: [{ field: 'aKey', operator:
|
|
23
|
+
filters: [{ field: 'aKey', operator: OperatorTypes.IS_NULL, values: [] }],
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
26
|
it('decodes URI components', () => {
|
|
@@ -28,7 +28,7 @@ describe('filters middleware', () => {
|
|
|
28
28
|
const response = { locals: {} };
|
|
29
29
|
extractFilters(request, response, () => { });
|
|
30
30
|
assert.deepEqual(response.locals, {
|
|
31
|
-
filters: [{ field: 'status', operator:
|
|
31
|
+
filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['foo,bar!!,?baz=!>qux'] }],
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
34
|
it('no data', () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import extractSearch from '../../src/middlewares/search.js';
|
|
4
|
+
describe('search middleware', () => {
|
|
5
|
+
it('data', () => {
|
|
6
|
+
const request = { query: { search: 'foo bar spam baz' } };
|
|
7
|
+
const response = { locals: {} };
|
|
8
|
+
extractSearch(request, response, () => { });
|
|
9
|
+
assert.deepEqual(response.locals, {
|
|
10
|
+
search: 'foo bar spam baz',
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
it('no data', () => {
|
|
14
|
+
const request = { query: {} };
|
|
15
|
+
const response = { locals: {} };
|
|
16
|
+
extractSearch(request, response, () => { });
|
|
17
|
+
assert.deepEqual(response.locals, {
|
|
18
|
+
search: null,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unito/integration-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Integration SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
"./package.json": "./package.json",
|
|
9
9
|
".": {
|
|
10
|
-
"import":
|
|
11
|
-
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/src/index.d.ts",
|
|
12
|
+
"default": "./dist/src/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/src/index.d.ts",
|
|
16
|
+
"default": "./dist/src/index.cjs"
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
},
|
|
14
20
|
"license": "LicenseRef-LICENSE",
|
|
@@ -46,7 +52,7 @@
|
|
|
46
52
|
"typescript": "5.x"
|
|
47
53
|
},
|
|
48
54
|
"dependencies": {
|
|
49
|
-
"@unito/integration-api": "
|
|
55
|
+
"@unito/integration-api": "3.x",
|
|
50
56
|
"busboy": "^1.6.0",
|
|
51
57
|
"cachette": "2.x",
|
|
52
58
|
"express": "^5.x",
|
package/src/handler.ts
CHANGED
|
@@ -297,6 +297,7 @@ export class Handler {
|
|
|
297
297
|
const collection = await handler({
|
|
298
298
|
credentials: res.locals.credentials,
|
|
299
299
|
secrets: res.locals.secrets,
|
|
300
|
+
search: res.locals.search,
|
|
300
301
|
selects: res.locals.selects,
|
|
301
302
|
filters: res.locals.filters,
|
|
302
303
|
logger: res.locals.logger,
|
package/src/integration.ts
CHANGED
|
@@ -12,6 +12,7 @@ import notFoundMiddleware from './middlewares/notFound.js';
|
|
|
12
12
|
import loggerMiddleware from './middlewares/logger.js';
|
|
13
13
|
import startMiddleware from './middlewares/start.js';
|
|
14
14
|
import secretsMiddleware from './middlewares/secrets.js';
|
|
15
|
+
import searchMiddleware from './middlewares/search.js';
|
|
15
16
|
import selectsMiddleware from './middlewares/selects.js';
|
|
16
17
|
import relationsMiddleware from './middlewares/relations.js';
|
|
17
18
|
import signalMiddleware from './middlewares/signal.js';
|
|
@@ -149,6 +150,7 @@ export default class Integration {
|
|
|
149
150
|
app.use(credentialsMiddleware);
|
|
150
151
|
app.use(secretsMiddleware);
|
|
151
152
|
app.use(filtersMiddleware);
|
|
153
|
+
app.use(searchMiddleware);
|
|
152
154
|
app.use(selectsMiddleware);
|
|
153
155
|
app.use(relationsMiddleware);
|
|
154
156
|
app.use(signalMiddleware);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OperatorType } from '@unito/integration-api';
|
|
1
|
+
import { OperatorType, OperatorTypes } from '@unito/integration-api';
|
|
2
2
|
import { Request, Response, NextFunction } from 'express';
|
|
3
3
|
|
|
4
4
|
declare global {
|
|
@@ -32,7 +32,7 @@ export type Filter = {
|
|
|
32
32
|
// a subset of the symbol of another operator.
|
|
33
33
|
//
|
|
34
34
|
// For example, the symbol "=" (EQUAL) is a subset of the symbol "!=" (NOT_EQUAL).
|
|
35
|
-
const ORDERED_OPERATORS = Object.values(
|
|
35
|
+
const ORDERED_OPERATORS = Object.values(OperatorTypes).sort((o1, o2) => o2.length - o1.length);
|
|
36
36
|
|
|
37
37
|
function extractFilters(req: Request, res: Response, next: NextFunction) {
|
|
38
38
|
const rawFilters = req.query.filter;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
5
|
+
namespace Express {
|
|
6
|
+
interface Locals {
|
|
7
|
+
// When the query params contains...
|
|
8
|
+
//
|
|
9
|
+
// search=foo
|
|
10
|
+
//
|
|
11
|
+
// ... it becomes available as follow in handlers:
|
|
12
|
+
//
|
|
13
|
+
// 'foo'
|
|
14
|
+
search: string | null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function extractSearch(req: Request, res: Response, next: NextFunction) {
|
|
20
|
+
const rawSearch = req.query.search;
|
|
21
|
+
|
|
22
|
+
if (typeof rawSearch === 'string') {
|
|
23
|
+
res.locals.search = rawSearch;
|
|
24
|
+
} else {
|
|
25
|
+
res.locals.search = null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
next();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default extractSearch;
|
package/src/resources/context.ts
CHANGED
|
@@ -96,6 +96,16 @@ export type GetCollectionContext<P extends Maybe<Params> = Empty, Q extends Quer
|
|
|
96
96
|
* @see {@link Filter}
|
|
97
97
|
*/
|
|
98
98
|
filters: Filter[];
|
|
99
|
+
/**
|
|
100
|
+
* Parsed search query param yielding a free-text search query.
|
|
101
|
+
*
|
|
102
|
+
* Given a search query param:
|
|
103
|
+
* `search=John`
|
|
104
|
+
*
|
|
105
|
+
* Context.search will be:
|
|
106
|
+
* 'John'
|
|
107
|
+
*/
|
|
108
|
+
search: string | null;
|
|
99
109
|
/**
|
|
100
110
|
* Parsed select query param yielding a list of fields to select.
|
|
101
111
|
*
|
package/test/helpers.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldValueTypes, OperatorTypes, Semantics } from '@unito/integration-api';
|
|
2
2
|
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { describe, it } from 'node:test';
|
|
@@ -10,20 +10,20 @@ describe('Helpers', () => {
|
|
|
10
10
|
const actual = getApplicableFilters(
|
|
11
11
|
{
|
|
12
12
|
filters: [
|
|
13
|
-
{ field: 'status', operator:
|
|
14
|
-
{ field: 'email', operator:
|
|
13
|
+
{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] },
|
|
14
|
+
{ field: 'email', operator: OperatorTypes.IS_NOT_NULL, values: [] },
|
|
15
15
|
],
|
|
16
16
|
},
|
|
17
17
|
[
|
|
18
18
|
{
|
|
19
19
|
name: 'status',
|
|
20
20
|
label: 'Status',
|
|
21
|
-
type:
|
|
21
|
+
type: FieldValueTypes.STRING,
|
|
22
22
|
},
|
|
23
23
|
],
|
|
24
24
|
);
|
|
25
25
|
|
|
26
|
-
const expected = [{ field: 'status', operator:
|
|
26
|
+
const expected = [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] }];
|
|
27
27
|
|
|
28
28
|
assert.deepEqual(actual, expected);
|
|
29
29
|
});
|
|
@@ -32,21 +32,21 @@ describe('Helpers', () => {
|
|
|
32
32
|
const actual = getApplicableFilters(
|
|
33
33
|
{
|
|
34
34
|
filters: [
|
|
35
|
-
{ field: 'semantic:displayName', operator:
|
|
36
|
-
{ field: 'semantic:createdAt', operator:
|
|
35
|
+
{ field: 'semantic:displayName', operator: OperatorTypes.START_WITH, values: ['Bob'] },
|
|
36
|
+
{ field: 'semantic:createdAt', operator: OperatorTypes.EQUAL, values: ['2021-01-01'] },
|
|
37
37
|
],
|
|
38
38
|
},
|
|
39
39
|
[
|
|
40
40
|
{
|
|
41
41
|
name: 'name',
|
|
42
42
|
label: 'Name',
|
|
43
|
-
type:
|
|
44
|
-
semantic:
|
|
43
|
+
type: FieldValueTypes.STRING,
|
|
44
|
+
semantic: Semantics.DISPLAY_NAME,
|
|
45
45
|
},
|
|
46
46
|
],
|
|
47
47
|
);
|
|
48
48
|
|
|
49
|
-
const expected = [{ field: 'name', operator:
|
|
49
|
+
const expected = [{ field: 'name', operator: OperatorTypes.START_WITH, values: ['Bob'] }];
|
|
50
50
|
|
|
51
51
|
assert.deepEqual(actual, expected);
|
|
52
52
|
});
|
|
@@ -55,16 +55,16 @@ describe('Helpers', () => {
|
|
|
55
55
|
const actual = getApplicableFilters(
|
|
56
56
|
{
|
|
57
57
|
filters: [
|
|
58
|
-
{ field: '...', operator:
|
|
59
|
-
{ field: ':', operator:
|
|
60
|
-
{ field: '', operator:
|
|
58
|
+
{ field: '...', operator: OperatorTypes.EQUAL, values: [] },
|
|
59
|
+
{ field: ':', operator: OperatorTypes.EQUAL, values: [] },
|
|
60
|
+
{ field: '', operator: OperatorTypes.EQUAL, values: [] },
|
|
61
61
|
],
|
|
62
62
|
},
|
|
63
63
|
[
|
|
64
64
|
{
|
|
65
65
|
name: 'status',
|
|
66
66
|
label: 'Status',
|
|
67
|
-
type:
|
|
67
|
+
type: FieldValueTypes.STRING,
|
|
68
68
|
},
|
|
69
69
|
],
|
|
70
70
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OperatorTypes } from '@unito/integration-api';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { describe, it } from 'node:test';
|
|
@@ -6,7 +6,7 @@ import extractFilters from '../../src/middlewares/filters.js';
|
|
|
6
6
|
|
|
7
7
|
describe('filters middleware', () => {
|
|
8
8
|
it('properly parse operators', () => {
|
|
9
|
-
Object.values(
|
|
9
|
+
Object.values(OperatorTypes).forEach(operator => {
|
|
10
10
|
const request = {
|
|
11
11
|
query: { filter: `aKey${operator}value` },
|
|
12
12
|
} as express.Request<
|
|
@@ -41,7 +41,7 @@ describe('filters middleware', () => {
|
|
|
41
41
|
extractFilters(request, response, () => {});
|
|
42
42
|
|
|
43
43
|
assert.deepEqual(response.locals, {
|
|
44
|
-
filters: [{ field: 'aKey', operator:
|
|
44
|
+
filters: [{ field: 'aKey', operator: OperatorTypes.IS_NULL, values: [] }],
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
|
|
@@ -58,7 +58,7 @@ describe('filters middleware', () => {
|
|
|
58
58
|
extractFilters(request, response, () => {});
|
|
59
59
|
|
|
60
60
|
assert.deepEqual(response.locals, {
|
|
61
|
-
filters: [{ field: 'status', operator:
|
|
61
|
+
filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['foo,bar!!,?baz=!>qux'] }],
|
|
62
62
|
});
|
|
63
63
|
});
|
|
64
64
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
|
+
import extractSearch from '../../src/middlewares/search.js';
|
|
5
|
+
|
|
6
|
+
describe('search middleware', () => {
|
|
7
|
+
it('data', () => {
|
|
8
|
+
const request = { query: { search: 'foo bar spam baz' } } as express.Request<
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
any,
|
|
11
|
+
object,
|
|
12
|
+
object,
|
|
13
|
+
{ search: string }
|
|
14
|
+
>;
|
|
15
|
+
const response = { locals: {} } as express.Response;
|
|
16
|
+
|
|
17
|
+
extractSearch(request, response, () => {});
|
|
18
|
+
|
|
19
|
+
assert.deepEqual(response.locals, {
|
|
20
|
+
search: 'foo bar spam baz',
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('no data', () => {
|
|
25
|
+
const request = { query: {} } as express.Request;
|
|
26
|
+
const response = { locals: {} } as express.Response;
|
|
27
|
+
|
|
28
|
+
extractSearch(request, response, () => {});
|
|
29
|
+
|
|
30
|
+
assert.deepEqual(response.locals, {
|
|
31
|
+
search: null,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|