@opengis/fastify-table 1.1.17 → 1.1.18
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/Changelog.md +4 -0
- package/hook/funcs/addHook.js +8 -0
- package/hook/funcs/applyHook.js +24 -0
- package/hook/funcs/hookList.js +1 -0
- package/hook/index.js +6 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/table/controllers/data.js +14 -4
- package/table/controllers/table.js +10 -2
- package/test/api/applyHook.test.js +96 -0
- package/utils.js +4 -0
package/Changelog.md
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import config from '../../config.js';
|
|
2
|
+
import hookList from './hookList.js';
|
|
3
|
+
|
|
4
|
+
export default async function applyHook(name, data) {
|
|
5
|
+
const debug = config.local || config.debug;
|
|
6
|
+
if (debug) console.log('applyHook', name);
|
|
7
|
+
if (!hookList[name]?.length) return null;
|
|
8
|
+
const result = {};
|
|
9
|
+
await Promise.all(hookList[name].map(async (hook) => {
|
|
10
|
+
const hookData = await hook({ ...data, config });
|
|
11
|
+
if (hookData) {
|
|
12
|
+
if (debug) console.log('applyHook', name, hookData);
|
|
13
|
+
Object.assign(result, hookData);
|
|
14
|
+
}
|
|
15
|
+
})).catch((err) => {
|
|
16
|
+
console.error('applyHook', name, err.toString());
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (Object.keys(result).length) {
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
package/hook/index.js
ADDED
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import crudPlugin from './crud/index.js';
|
|
|
14
14
|
import policyPlugin from './policy/index.js';
|
|
15
15
|
import utilPlugin from './util/index.js';
|
|
16
16
|
import cronPlugin from './cron/index.js';
|
|
17
|
+
import hookPlugin from './hook/index.js';
|
|
17
18
|
|
|
18
19
|
import pgClients from './pg/pgClients.js';
|
|
19
20
|
|
|
@@ -92,6 +93,7 @@ async function plugin(fastify, opt) {
|
|
|
92
93
|
widgetPlugin(fastify, opt);
|
|
93
94
|
utilPlugin(fastify, opt);
|
|
94
95
|
cronPlugin(fastify, opt);
|
|
96
|
+
hookPlugin(fastify, opt);
|
|
95
97
|
}
|
|
96
98
|
export default fp(plugin);
|
|
97
99
|
// export { rclient };
|
package/package.json
CHANGED
|
@@ -6,16 +6,24 @@ import getAccess from '../../crud/funcs/getAccess.js';
|
|
|
6
6
|
import setToken from '../../crud/funcs/setToken.js';
|
|
7
7
|
import gisIRColumn from './utils/gisIRColumn.js';
|
|
8
8
|
|
|
9
|
+
import { applyHook } from '../../utils.js';
|
|
10
|
+
|
|
9
11
|
const maxLimit = 100;
|
|
10
|
-
export default async function dataAPI({
|
|
11
|
-
|
|
12
|
-
}
|
|
12
|
+
export default async function dataAPI(req) {
|
|
13
|
+
const {
|
|
14
|
+
pg, params, funcs = {}, query = {}, opt = {}, uid: uid1, session,
|
|
15
|
+
} = req;
|
|
13
16
|
const time = Date.now();
|
|
14
17
|
|
|
15
18
|
const uid = session?.passport?.user?.uid || uid1 || query.uid || 0;
|
|
16
19
|
|
|
17
20
|
const loadTable = await getTemplate('table', params.table);
|
|
18
21
|
|
|
22
|
+
const check = await applyHook('preData', { req });
|
|
23
|
+
if (check?.message && check?.status) {
|
|
24
|
+
return { message: check?.message, status: check?.status };
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
if (!loadTable) { return { message: 'template not found', status: 404 }; }
|
|
20
28
|
|
|
21
29
|
const {
|
|
@@ -104,5 +112,7 @@ export default async function dataAPI({
|
|
|
104
112
|
});
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
|
|
115
|
+
const result = await applyHook('afterData', { req, table: loadTable.table, res });
|
|
116
|
+
|
|
117
|
+
return result || res;
|
|
108
118
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import getTemplate from './utils/getTemplate.js';
|
|
2
2
|
import getMeta from '../../pg/funcs/getMeta.js';
|
|
3
3
|
|
|
4
|
+
import { applyHook } from '../../utils.js';
|
|
5
|
+
|
|
4
6
|
export default async function tableAPI(req) {
|
|
5
7
|
const {
|
|
6
|
-
pg, params = {}, query = {}, opt = {},
|
|
8
|
+
pg, params = {}, query = {}, opt = {}, funcs,
|
|
7
9
|
} = req;
|
|
8
10
|
if (!params.id) return { message: 'not enough params', status: 400 };
|
|
9
11
|
|
|
@@ -12,6 +14,11 @@ export default async function tableAPI(req) {
|
|
|
12
14
|
if (!pg.pk?.[opt?.table || params.table]) { return { message: 'not found', status: 404 }; }
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
const check = await applyHook('preTable', { req });
|
|
18
|
+
if (check?.message && check?.status) {
|
|
19
|
+
return { message: check?.message, status: check?.status };
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
const {
|
|
16
23
|
table, /* columns, */ form,
|
|
17
24
|
} = loadTable;
|
|
@@ -48,5 +55,6 @@ export default async function tableAPI(req) {
|
|
|
48
55
|
}));
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
const res = await applyHook('afterTable', { req, table: loadTable?.table, rows });
|
|
59
|
+
return res || rows?.[0] || {};
|
|
52
60
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import pgClients from '../../pg/pgClients.js';
|
|
5
|
+
import init from '../../pg/funcs/init.js';
|
|
6
|
+
|
|
7
|
+
import build from '../../helper.js';
|
|
8
|
+
import config from '../config.js';
|
|
9
|
+
|
|
10
|
+
import { addTemplateDir, addHook } from '../../utils.js';
|
|
11
|
+
|
|
12
|
+
const prefix = config.prefix || '/api';
|
|
13
|
+
const table = 'gis.dataset.table';
|
|
14
|
+
|
|
15
|
+
test('applyHook to API data/table', async (t) => {
|
|
16
|
+
const app = await build(t);
|
|
17
|
+
const cwd = process.cwd();
|
|
18
|
+
await init(pgClients.client);
|
|
19
|
+
addTemplateDir(path.join(cwd, 'test/templates'));
|
|
20
|
+
|
|
21
|
+
addHook('preData', async ({ req }) => {
|
|
22
|
+
if (req.params?.table === `${table}1`) {
|
|
23
|
+
return { message: 'access restricted by hook', status: 403 };
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
});
|
|
27
|
+
addHook('preTable', async ({ req }) => {
|
|
28
|
+
const { params = {} } = req;
|
|
29
|
+
if (params?.table === `${table}1`) {
|
|
30
|
+
return { message: 'access restricted by hook', status: 403 };
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
addHook('afterData', async ({ res }) => {
|
|
36
|
+
Object.assign(res, { test: '1' });
|
|
37
|
+
});
|
|
38
|
+
addHook('afterTable', async ({ rows = [] }) => {
|
|
39
|
+
Object.assign(rows[0], { count: 1 });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await t.test('GET /data (preData ok)', async () => {
|
|
43
|
+
const res = await app.inject({
|
|
44
|
+
method: 'GET',
|
|
45
|
+
url: `${prefix}/data/${table}`,
|
|
46
|
+
});
|
|
47
|
+
const json = res.json();
|
|
48
|
+
assert.ok(json?.time, 'api error');
|
|
49
|
+
});
|
|
50
|
+
await t.test('GET /data (preData message)', async () => {
|
|
51
|
+
const res = await app.inject({
|
|
52
|
+
method: 'GET',
|
|
53
|
+
url: `${prefix}/data/${table}1`,
|
|
54
|
+
});
|
|
55
|
+
const json = res.json();
|
|
56
|
+
assert.ok(json.message === 'access restricted by hook', 'preData hook error');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await t.test('GET /data (afterData)', async () => {
|
|
60
|
+
const res = await app.inject({
|
|
61
|
+
method: 'GET',
|
|
62
|
+
url: `${prefix}/data/${table}`,
|
|
63
|
+
});
|
|
64
|
+
const json = res.json();
|
|
65
|
+
assert.ok(json?.test === '1', 'afterData hook error');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const { id = '1' } = pgClients.client?.pk['gis.dataset']
|
|
69
|
+
? await pgClients.client.query('select dataset_id as id from gis.dataset limit 1')
|
|
70
|
+
.then((res) => res.rows?.[0] || {}) : {};
|
|
71
|
+
await t.test('GET /table/:id (preTable ok)', async () => {
|
|
72
|
+
const res = await app.inject({
|
|
73
|
+
method: 'GET',
|
|
74
|
+
url: `${prefix}/table/${table}1/${id}`,
|
|
75
|
+
});
|
|
76
|
+
const json = res.json();
|
|
77
|
+
assert.ok(json.message === 'access restricted by hook', 'preTable hook error');
|
|
78
|
+
});
|
|
79
|
+
await t.test('GET /table/:id (preTable message)', async () => {
|
|
80
|
+
const res = await app.inject({
|
|
81
|
+
method: 'GET',
|
|
82
|
+
url: `${prefix}/table/${table}1/${id}`,
|
|
83
|
+
});
|
|
84
|
+
const json = res.json();
|
|
85
|
+
assert.ok(json.message === 'access restricted by hook', 'preTable hook error');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await t.test('GET /table/:id (afterTable)', async () => {
|
|
89
|
+
const res = await app.inject({
|
|
90
|
+
method: 'GET',
|
|
91
|
+
url: `${prefix}/table/${table}/${id}`,
|
|
92
|
+
});
|
|
93
|
+
const json = res.json();
|
|
94
|
+
assert.equal(json?.count, 1);
|
|
95
|
+
});
|
|
96
|
+
});
|
package/utils.js
CHANGED
|
@@ -24,6 +24,8 @@ import gisIRColumn from './table/controllers/utils/gisIRColumn.js';
|
|
|
24
24
|
import getMeta from './pg/funcs/getMeta.js';
|
|
25
25
|
import getAccess from './crud/funcs/getAccess.js';
|
|
26
26
|
import getSelectVal from './table/funcs/metaFormat/getSelectVal.js';
|
|
27
|
+
import applyHook from './hook/funcs/applyHook.js';
|
|
28
|
+
import addHook from './hook/funcs/addHook.js';
|
|
27
29
|
|
|
28
30
|
export default null;
|
|
29
31
|
export {
|
|
@@ -47,4 +49,6 @@ export {
|
|
|
47
49
|
getMeta,
|
|
48
50
|
getAccess,
|
|
49
51
|
getSelectVal,
|
|
52
|
+
applyHook,
|
|
53
|
+
addHook,
|
|
50
54
|
};
|