@quatrain/api-server-express 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +0 -3
- package/dist/index.js +1 -7
- package/package.json +4 -5
- package/src/adapters/ExpressAdapter.ts +1 -1
- package/src/index.ts +0 -4
- package/README.md +0 -13
- package/dist/endpoints/CrudEndpoint.d.ts +0 -3
- package/dist/endpoints/CrudEndpoint.js +0 -101
- package/dist/endpoints/ListEndpoint.d.ts +0 -3
- package/dist/endpoints/ListEndpoint.js +0 -27
- package/dist/endpoints/ValuesEndpoint.d.ts +0 -3
- package/dist/endpoints/ValuesEndpoint.js +0 -59
- package/src/endpoints/CrudEndpoint.ts +0 -106
- package/src/endpoints/ListEndpoint.ts +0 -30
- package/src/endpoints/ValuesEndpoint.ts +0 -66
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ExpressAdapter = void 0;
|
|
4
4
|
var ExpressAdapter_1 = require("./adapters/ExpressAdapter");
|
|
5
5
|
Object.defineProperty(exports, "ExpressAdapter", { enumerable: true, get: function () { return ExpressAdapter_1.ExpressAdapter; } });
|
|
6
|
-
var CrudEndpoint_1 = require("./endpoints/CrudEndpoint");
|
|
7
|
-
Object.defineProperty(exports, "CrudEndpoint", { enumerable: true, get: function () { return CrudEndpoint_1.CrudEndpoint; } });
|
|
8
|
-
var ListEndpoint_1 = require("./endpoints/ListEndpoint");
|
|
9
|
-
Object.defineProperty(exports, "ListEndpoint", { enumerable: true, get: function () { return ListEndpoint_1.ListEndpoint; } });
|
|
10
|
-
var ValuesEndpoint_1 = require("./endpoints/ValuesEndpoint");
|
|
11
|
-
Object.defineProperty(exports, "ValuesEndpoint", { enumerable: true, get: function () { return ValuesEndpoint_1.ValuesEndpoint; } });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quatrain/api-server-express",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.8",
|
|
4
|
+
"description": "Express Adapter for Quatrain API Server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bun": "src/index.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git+https://github.com/Quatrain/Core.git",
|
|
18
|
-
"directory": "packages/api-server"
|
|
18
|
+
"directory": "packages/api-server-express"
|
|
19
19
|
},
|
|
20
20
|
"author": "Quatrain Développement SAS <developers@quatrain.com>",
|
|
21
21
|
"license": "AGPL-3.0-only",
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@quatrain/api": "^1.1.4",
|
|
33
|
-
"@quatrain/
|
|
34
|
-
"@quatrain/core": "^1.2.5",
|
|
33
|
+
"@quatrain/api-server": "^1.1.8",
|
|
35
34
|
"express": "^4.19.2"
|
|
36
35
|
},
|
|
37
36
|
"scripts": {
|
package/src/index.ts
CHANGED
package/README.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# @quatrain/api-server-express
|
|
2
|
-
|
|
3
|
-
The `@quatrain/api-server-express` package provides the backend REST layer for Quatrain, exposing the underlying DataObjects and Backend engines through HTTP endpoints.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
- **Express Adapter**: A lightweight wrapper around Express to bootstrap APIs instantly.
|
|
7
|
-
- **Auto-generated Endpoints**: Pre-built `CrudEndpoint` and `ListEndpoint` handlers to instantly expose a Quatrain model (e.g. `StudioProperty`, `StudioModel`) as a complete REST API.
|
|
8
|
-
- **Middleware Support**: Pluggable Express middlewares.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
## Getting Started
|
|
12
|
-
|
|
13
|
-
Refer to the `HOWTO.md` file for usage examples.
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CrudEndpoint = void 0;
|
|
4
|
-
const backend_1 = require("@quatrain/backend");
|
|
5
|
-
const CrudEndpoint = (ModelClass) => {
|
|
6
|
-
return (router, path, options) => {
|
|
7
|
-
const methods = options.methods || ['CREATE', 'READ', 'UPDATE', 'DELETE'];
|
|
8
|
-
// C: Create
|
|
9
|
-
if (methods.includes('CREATE')) {
|
|
10
|
-
router.post(path, async (req, res) => {
|
|
11
|
-
try {
|
|
12
|
-
const data = req.body;
|
|
13
|
-
const newObj = await ModelClass.factory();
|
|
14
|
-
Object.keys(data).forEach((key) => {
|
|
15
|
-
if (newObj.has(key)) {
|
|
16
|
-
newObj.set(key, data[key]);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
newObj.validate();
|
|
20
|
-
await newObj.save();
|
|
21
|
-
res.status(201).json(newObj.dataObject.toJSON());
|
|
22
|
-
}
|
|
23
|
-
catch (e) {
|
|
24
|
-
if (e.name === 'ValidationError') {
|
|
25
|
-
res.status(400).json({ error: e.message, validationErrors: e.errors });
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
backend_1.Backend.error(`[API Error] POST: ${e.message}`);
|
|
29
|
-
res.status(400).json({ error: e.message });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
// R: Read (Single by ID)
|
|
35
|
-
if (methods.includes('READ')) {
|
|
36
|
-
const getPath = path.endsWith('/') ? `${path}:id` : `${path}/:id`;
|
|
37
|
-
router.get(getPath, async (req, res) => {
|
|
38
|
-
try {
|
|
39
|
-
const obj = await ModelClass.fromBackend(req.params.id);
|
|
40
|
-
if (!obj) {
|
|
41
|
-
return res.status(404).json({ error: 'Object not found' });
|
|
42
|
-
}
|
|
43
|
-
res.json(obj.dataObject.toJSON());
|
|
44
|
-
}
|
|
45
|
-
catch (e) {
|
|
46
|
-
backend_1.Backend.error(`[API Error] GET /${req.params.id}: ${e.message}`);
|
|
47
|
-
res.status(500).json({ error: e.message });
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
// U: Update
|
|
52
|
-
if (methods.includes('UPDATE')) {
|
|
53
|
-
const putPath = path.endsWith('/') ? `${path}:id` : `${path}/:id`;
|
|
54
|
-
router.put(putPath, async (req, res) => {
|
|
55
|
-
try {
|
|
56
|
-
const data = req.body;
|
|
57
|
-
const obj = await ModelClass.fromBackend(req.params.id);
|
|
58
|
-
if (!obj) {
|
|
59
|
-
return res.status(404).json({ error: 'Object not found' });
|
|
60
|
-
}
|
|
61
|
-
Object.keys(data).forEach((key) => {
|
|
62
|
-
if (obj.has(key)) {
|
|
63
|
-
obj.set(key, data[key]);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
obj.validate();
|
|
67
|
-
await obj.save();
|
|
68
|
-
res.json(obj.dataObject.toJSON());
|
|
69
|
-
}
|
|
70
|
-
catch (e) {
|
|
71
|
-
if (e.name === 'ValidationError') {
|
|
72
|
-
res.status(400).json({ error: e.message, validationErrors: e.errors });
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
backend_1.Backend.error(`[API Error] PUT /${req.params.id}: ${e.message}`);
|
|
76
|
-
res.status(400).json({ error: e.message });
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
// D: Delete
|
|
82
|
-
if (methods.includes('DELETE')) {
|
|
83
|
-
const deletePath = path.endsWith('/') ? `${path}:id` : `${path}/:id`;
|
|
84
|
-
router.delete(deletePath, async (req, res) => {
|
|
85
|
-
try {
|
|
86
|
-
const obj = await ModelClass.fromBackend(req.params.id);
|
|
87
|
-
if (!obj) {
|
|
88
|
-
return res.status(404).json({ error: 'Object not found' });
|
|
89
|
-
}
|
|
90
|
-
await obj.delete();
|
|
91
|
-
res.json({ success: true });
|
|
92
|
-
}
|
|
93
|
-
catch (e) {
|
|
94
|
-
backend_1.Backend.error(`[API Error] DELETE /${req.params.id}: ${e.message}`);
|
|
95
|
-
res.status(500).json({ error: e.message });
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
};
|
|
101
|
-
exports.CrudEndpoint = CrudEndpoint;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ListEndpoint = void 0;
|
|
4
|
-
const backend_1 = require("@quatrain/backend");
|
|
5
|
-
const ListEndpoint = (ModelClass) => {
|
|
6
|
-
return (router, path, options) => {
|
|
7
|
-
router.get(path, async (req, res) => {
|
|
8
|
-
try {
|
|
9
|
-
let q = ModelClass.query();
|
|
10
|
-
// Apply all query parameters as exact match filters
|
|
11
|
-
for (const [key, value] of Object.entries(req.query)) {
|
|
12
|
-
q = q.where(key, value, 'equals');
|
|
13
|
-
}
|
|
14
|
-
const results = await q.execute('dataObjects');
|
|
15
|
-
res.json({
|
|
16
|
-
items: results.items.map((r) => r.toJSON()),
|
|
17
|
-
meta: results.meta
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
catch (e) {
|
|
21
|
-
backend_1.Backend.error(`[API Error] GET (List): ${e.message}`);
|
|
22
|
-
res.status(500).json({ error: e.message });
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
exports.ListEndpoint = ListEndpoint;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ValuesEndpoint = void 0;
|
|
4
|
-
const backend_1 = require("@quatrain/backend");
|
|
5
|
-
const ValuesEndpoint = (ModelClass) => {
|
|
6
|
-
return (router, path, options) => {
|
|
7
|
-
// Create the endpoint route, assuming 'path' is something like '/api/users'
|
|
8
|
-
// We'll map it to '/api/users/values'
|
|
9
|
-
const valuesPath = path.endsWith('/') ? `${path}values` : `${path}/values`;
|
|
10
|
-
router.get(valuesPath, async (req, res) => {
|
|
11
|
-
try {
|
|
12
|
-
const results = await ModelClass.query()
|
|
13
|
-
.where('status', 'deleted', 'notEquals')
|
|
14
|
-
.execute('dataObjects');
|
|
15
|
-
// Identify exposed fields from PROPS_DEFINITION
|
|
16
|
-
const propsDef = ModelClass.PROPS_DEFINITION || [];
|
|
17
|
-
const exposedFields = propsDef
|
|
18
|
-
.filter((p) => p.htmlType && p.htmlType !== 'off')
|
|
19
|
-
.map((p) => p.name);
|
|
20
|
-
const searchFields = ['name', ...propsDef
|
|
21
|
-
.filter((p) => p.type === 'StringProperty' && p.fullSearch === true)
|
|
22
|
-
.map((p) => p.name)];
|
|
23
|
-
let values = results.items.map((dataObject) => {
|
|
24
|
-
const payload = {
|
|
25
|
-
value: dataObject.uid,
|
|
26
|
-
name: dataObject.has('name') ? dataObject.get('name') : dataObject.uid
|
|
27
|
-
};
|
|
28
|
-
for (const field of exposedFields) {
|
|
29
|
-
if (dataObject.has(field)) {
|
|
30
|
-
payload[field] = dataObject.get(field);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const searchVals = searchFields.map(f => {
|
|
34
|
-
const val = dataObject.get(f);
|
|
35
|
-
return typeof val === 'string' ? val : '';
|
|
36
|
-
}).filter(Boolean);
|
|
37
|
-
payload._search = searchVals.join(' ').toLowerCase();
|
|
38
|
-
return payload;
|
|
39
|
-
});
|
|
40
|
-
const qParam = req.query.q;
|
|
41
|
-
if (qParam) {
|
|
42
|
-
const searchStr = qParam.toLowerCase();
|
|
43
|
-
values = values.filter((payload) => {
|
|
44
|
-
return searchFields.some(field => {
|
|
45
|
-
const val = payload[field];
|
|
46
|
-
return typeof val === 'string' && val.toLowerCase().includes(searchStr);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
res.json(values);
|
|
51
|
-
}
|
|
52
|
-
catch (e) {
|
|
53
|
-
backend_1.Backend.error(`[API Error] GET ${valuesPath}: ${e.message}`);
|
|
54
|
-
res.status(500).json({ error: e.message });
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
exports.ValuesEndpoint = ValuesEndpoint;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { EndpointHandler, ServerAdapter, EndpointOptions } from '@quatrain/api'
|
|
2
|
-
import { BaseObject, DataObjectClass } from '@quatrain/core'
|
|
3
|
-
import { Backend } from '@quatrain/backend'
|
|
4
|
-
import { ValidationError } from '@quatrain/core'
|
|
5
|
-
|
|
6
|
-
export const CrudEndpoint = (ModelClass: typeof BaseObject): EndpointHandler => {
|
|
7
|
-
return (router: ServerAdapter, path: string, options: EndpointOptions) => {
|
|
8
|
-
const methods = options.methods || ['CREATE', 'READ', 'UPDATE', 'DELETE']
|
|
9
|
-
|
|
10
|
-
// C: Create
|
|
11
|
-
if (methods.includes('CREATE')) {
|
|
12
|
-
router.post(path, async (req, res) => {
|
|
13
|
-
try {
|
|
14
|
-
const data = req.body
|
|
15
|
-
const newObj = await ModelClass.factory()
|
|
16
|
-
|
|
17
|
-
Object.keys(data).forEach((key) => {
|
|
18
|
-
if (newObj.has(key)) {
|
|
19
|
-
newObj.set(key, data[key])
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
(newObj as any).validate()
|
|
24
|
-
await (newObj as any).save()
|
|
25
|
-
res.status(201).json(newObj.dataObject.toJSON())
|
|
26
|
-
} catch (e: any) {
|
|
27
|
-
if (e.name === 'ValidationError') {
|
|
28
|
-
res.status(400).json({ error: e.message, validationErrors: e.errors })
|
|
29
|
-
} else {
|
|
30
|
-
Backend.error(`[API Error] POST: ${e.message}`)
|
|
31
|
-
res.status(400).json({ error: e.message })
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// R: Read (Single by ID)
|
|
38
|
-
if (methods.includes('READ')) {
|
|
39
|
-
const getPath = path.endsWith('/') ? `${path}:id` : `${path}/:id`
|
|
40
|
-
router.get(getPath, async (req, res) => {
|
|
41
|
-
try {
|
|
42
|
-
const obj = await (ModelClass as any).fromBackend(req.params.id)
|
|
43
|
-
if (!obj) {
|
|
44
|
-
return res.status(404).json({ error: 'Object not found' })
|
|
45
|
-
}
|
|
46
|
-
res.json(obj.dataObject.toJSON())
|
|
47
|
-
} catch (e) {
|
|
48
|
-
Backend.error(`[API Error] GET /${req.params.id}: ${(e as Error).message}`)
|
|
49
|
-
res.status(500).json({ error: (e as Error).message })
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// U: Update
|
|
55
|
-
if (methods.includes('UPDATE')) {
|
|
56
|
-
const putPath = path.endsWith('/') ? `${path}:id` : `${path}/:id`
|
|
57
|
-
router.put(putPath, async (req, res) => {
|
|
58
|
-
try {
|
|
59
|
-
const data = req.body
|
|
60
|
-
const obj = await (ModelClass as any).fromBackend(req.params.id)
|
|
61
|
-
|
|
62
|
-
if (!obj) {
|
|
63
|
-
return res.status(404).json({ error: 'Object not found' })
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
Object.keys(data).forEach((key) => {
|
|
67
|
-
if (obj.has(key)) {
|
|
68
|
-
obj.set(key, data[key])
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
obj.validate()
|
|
73
|
-
await obj.save()
|
|
74
|
-
res.json(obj.dataObject.toJSON())
|
|
75
|
-
} catch (e: any) {
|
|
76
|
-
if (e.name === 'ValidationError') {
|
|
77
|
-
res.status(400).json({ error: e.message, validationErrors: e.errors })
|
|
78
|
-
} else {
|
|
79
|
-
Backend.error(`[API Error] PUT /${req.params.id}: ${e.message}`)
|
|
80
|
-
res.status(400).json({ error: e.message })
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// D: Delete
|
|
87
|
-
if (methods.includes('DELETE')) {
|
|
88
|
-
const deletePath = path.endsWith('/') ? `${path}:id` : `${path}/:id`
|
|
89
|
-
router.delete(deletePath, async (req, res) => {
|
|
90
|
-
try {
|
|
91
|
-
const obj = await (ModelClass as any).fromBackend(req.params.id)
|
|
92
|
-
|
|
93
|
-
if (!obj) {
|
|
94
|
-
return res.status(404).json({ error: 'Object not found' })
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await obj.delete()
|
|
98
|
-
res.json({ success: true })
|
|
99
|
-
} catch (e) {
|
|
100
|
-
Backend.error(`[API Error] DELETE /${req.params.id}: ${(e as Error).message}`)
|
|
101
|
-
res.status(500).json({ error: (e as Error).message })
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { EndpointHandler, ServerAdapter, EndpointOptions } from '@quatrain/api'
|
|
2
|
-
import { BaseObject, DataObjectClass } from '@quatrain/core'
|
|
3
|
-
import { Backend } from '@quatrain/backend'
|
|
4
|
-
|
|
5
|
-
export const ListEndpoint = (ModelClass: typeof BaseObject): EndpointHandler => {
|
|
6
|
-
return (router: ServerAdapter, path: string, options: EndpointOptions) => {
|
|
7
|
-
|
|
8
|
-
router.get(path, async (req, res) => {
|
|
9
|
-
try {
|
|
10
|
-
let q = (ModelClass as any).query()
|
|
11
|
-
|
|
12
|
-
// Apply all query parameters as exact match filters
|
|
13
|
-
for (const [key, value] of Object.entries(req.query)) {
|
|
14
|
-
q = q.where(key, value, 'equals')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const results = await q.execute('dataObjects')
|
|
18
|
-
|
|
19
|
-
res.json({
|
|
20
|
-
items: results.items.map((r: DataObjectClass<any>) => r.toJSON()),
|
|
21
|
-
meta: results.meta
|
|
22
|
-
})
|
|
23
|
-
} catch (e) {
|
|
24
|
-
Backend.error(`[API Error] GET (List): ${(e as Error).message}`)
|
|
25
|
-
res.status(500).json({ error: (e as Error).message })
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { EndpointHandler, ServerAdapter, EndpointOptions } from '@quatrain/api'
|
|
2
|
-
import { BaseObject, DataObjectClass } from '@quatrain/core'
|
|
3
|
-
import { Backend } from '@quatrain/backend'
|
|
4
|
-
|
|
5
|
-
export const ValuesEndpoint = (ModelClass: typeof BaseObject): EndpointHandler => {
|
|
6
|
-
return (router: ServerAdapter, path: string, options: EndpointOptions) => {
|
|
7
|
-
// Create the endpoint route, assuming 'path' is something like '/api/users'
|
|
8
|
-
// We'll map it to '/api/users/values'
|
|
9
|
-
const valuesPath = path.endsWith('/') ? `${path}values` : `${path}/values`
|
|
10
|
-
|
|
11
|
-
router.get(valuesPath, async (req, res) => {
|
|
12
|
-
try {
|
|
13
|
-
const results = await (ModelClass as any).query()
|
|
14
|
-
.where('status', 'deleted', 'notEquals')
|
|
15
|
-
.execute('dataObjects')
|
|
16
|
-
|
|
17
|
-
// Identify exposed fields from PROPS_DEFINITION
|
|
18
|
-
const propsDef = (ModelClass as any).PROPS_DEFINITION || []
|
|
19
|
-
const exposedFields = propsDef
|
|
20
|
-
.filter((p: any) => p.htmlType && p.htmlType !== 'off')
|
|
21
|
-
.map((p: any) => p.name)
|
|
22
|
-
|
|
23
|
-
const searchFields = ['name', ...propsDef
|
|
24
|
-
.filter((p: any) => p.type === 'StringProperty' && p.fullSearch === true)
|
|
25
|
-
.map((p: any) => p.name)]
|
|
26
|
-
|
|
27
|
-
let values = results.items.map((dataObject: DataObjectClass<any>) => {
|
|
28
|
-
const payload: any = {
|
|
29
|
-
value: dataObject.uid,
|
|
30
|
-
name: dataObject.has('name') ? dataObject.get('name') : dataObject.uid
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for (const field of exposedFields) {
|
|
34
|
-
if (dataObject.has(field)) {
|
|
35
|
-
payload[field] = dataObject.get(field)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const searchVals = searchFields.map(f => {
|
|
40
|
-
const val = dataObject.get(f)
|
|
41
|
-
return typeof val === 'string' ? val : ''
|
|
42
|
-
}).filter(Boolean)
|
|
43
|
-
payload._search = searchVals.join(' ').toLowerCase()
|
|
44
|
-
|
|
45
|
-
return payload
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
const qParam = req.query.q as string
|
|
49
|
-
if (qParam) {
|
|
50
|
-
const searchStr = qParam.toLowerCase()
|
|
51
|
-
values = values.filter((payload: any) => {
|
|
52
|
-
return searchFields.some(field => {
|
|
53
|
-
const val = payload[field]
|
|
54
|
-
return typeof val === 'string' && val.toLowerCase().includes(searchStr)
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
res.json(values)
|
|
60
|
-
} catch (e) {
|
|
61
|
-
Backend.error(`[API Error] GET ${valuesPath}: ${(e as Error).message}`)
|
|
62
|
-
res.status(500).json({ error: (e as Error).message })
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
}
|