@opengis/fastify-table 2.5.0 → 2.5.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/server/migrations/users.sql +11 -1
- package/dist/server/plugins/crud/funcs/utils/logChanges.d.ts.map +1 -1
- package/dist/server/plugins/crud/funcs/utils/logChanges.js +5 -2
- package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
- package/dist/server/plugins/policy/funcs/checkPolicy.js +4 -1
- package/dist/server/plugins/table/funcs/getSelectMeta.d.ts.map +1 -1
- package/dist/server/plugins/table/funcs/getSelectMeta.js +10 -5
- package/dist/server/routes/access/schema.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/export.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/export.js +5 -3
- package/dist/server/routes/file/controllers/resizeAll.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/resizeAll.js +4 -3
- package/dist/server/routes/file/index.d.ts.map +1 -1
- package/dist/server/routes/file/index.js +20 -5
- package/dist/server/routes/file/schema.d.ts +27 -4
- package/dist/server/routes/file/schema.d.ts.map +1 -1
- package/dist/server/routes/file/schema.js +23 -9
- package/dist/server/routes/table/controllers/search.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/search.js +19 -11
- package/dist/server/routes/table/controllers/suggest.js +1 -1
- package/dist/server/routes/table/functions/getData.d.ts +1 -1
- package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
- package/dist/server/routes/table/functions/getData.js +80 -46
- package/dist/server/routes/table/index.js +2 -1
- package/dist/server/routes/table/schema.d.ts +6 -10
- package/dist/server/routes/table/schema.d.ts.map +1 -1
- package/dist/server/routes/table/schema.js +50 -50
- package/dist/server/routes/templates/index.d.ts.map +1 -1
- package/dist/server/routes/templates/index.js +7 -1
- package/dist/server/routes/templates/schema.d.ts +3 -3
- package/dist/server/routes/templates/schema.d.ts.map +1 -1
- package/dist/server/routes/templates/schema.js +4 -4
- package/package.json +1 -1
|
@@ -56,7 +56,17 @@ COMMENT ON COLUMN admin.users.salt IS 'Сіль';
|
|
|
56
56
|
COMMENT ON COLUMN admin.users.twofa IS 'Двофакторна авторизація';
|
|
57
57
|
|
|
58
58
|
CREATE EXTENSION if not exists pgcrypto SCHEMA public VERSION "1.3";
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
CREATE OR REPLACE FUNCTION admin.crypt(pass TEXT,salt TEXT)
|
|
61
|
+
RETURNS text AS
|
|
62
|
+
$BODY$
|
|
63
|
+
DECLARE
|
|
64
|
+
BEGIN
|
|
65
|
+
return public.crypt(pass, salt);
|
|
66
|
+
END;
|
|
67
|
+
$BODY$
|
|
68
|
+
LANGUAGE plpgsql VOLATILE
|
|
69
|
+
COST 100;
|
|
60
70
|
|
|
61
71
|
-- DROP FUNCTION admin.insert_update_user_before();
|
|
62
72
|
CREATE OR REPLACE FUNCTION admin.insert_update_user_before()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logChanges.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/logChanges.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"logChanges.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/logChanges.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAoD5D,wBAA8B,UAAU,CAAC,EACvC,EAAE,EACF,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,GAAO,EACP,IAAI,GACL,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;;;;;;;;;;;;;;;;;;;;UA0MA"}
|
|
@@ -4,6 +4,9 @@ import metaFormat from "../../../table/funcs/metaFormat/index.js";
|
|
|
4
4
|
import getMeta from "../../../pg/funcs/getMeta.js";
|
|
5
5
|
import config from "../../../../../config.js";
|
|
6
6
|
const logLength = +(config.logLength || 200);
|
|
7
|
+
const sequence = (arr, fn) => {
|
|
8
|
+
return arr.reduce((promise, item) => promise.then(() => fn(item)), Promise.resolve());
|
|
9
|
+
};
|
|
7
10
|
const defaultTitles = {
|
|
8
11
|
editor_date: "Дата оновлення",
|
|
9
12
|
editor_id: "Редактор",
|
|
@@ -157,7 +160,7 @@ export default async function logChanges({ pg, table: table1, tokenData, referer
|
|
|
157
160
|
if (process.env.NODE_ENV === "test") {
|
|
158
161
|
console.log("changesData", changesData);
|
|
159
162
|
}
|
|
160
|
-
const res = await
|
|
163
|
+
const res = await sequence(changesData, async (el) => {
|
|
161
164
|
const insertQuery = `insert into log.table_changes_data (${Object.entries(el)
|
|
162
165
|
?.map((key) => `"${key[0]}"`)
|
|
163
166
|
.join(",")})
|
|
@@ -174,7 +177,7 @@ export default async function logChanges({ pg, table: table1, tokenData, referer
|
|
|
174
177
|
])
|
|
175
178
|
.then((el) => el.rows?.[0] || {});
|
|
176
179
|
return row1;
|
|
177
|
-
})
|
|
180
|
+
});
|
|
178
181
|
const newData = (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {});
|
|
179
182
|
// console.log('logChanges OK', type);
|
|
180
183
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAMhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAMhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,GAAG,QAyKlE"}
|
|
@@ -67,7 +67,10 @@ export default function checkPolicy(req, jwt) {
|
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
69
|
// ! sql injection
|
|
70
|
-
const stopWords = block.filter((el) => path
|
|
70
|
+
const stopWords = block.filter((el) => decodeURIComponent(path).toUpperCase().includes(el.toUpperCase()) ||
|
|
71
|
+
JSON.stringify(req.body || {})
|
|
72
|
+
.toUpperCase()
|
|
73
|
+
.includes(el.toUpperCase()));
|
|
71
74
|
if (stopWords?.length && !allowSql) {
|
|
72
75
|
logger.file("injection/sql", {
|
|
73
76
|
path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getSelectMeta.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/table/funcs/getSelectMeta.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAWzD,wBAA8B,aAAa,CAAC,EAC1C,IAAI,EACJ,UAAU,EACV,GAAG,EACH,OAAO,EACP,MAAM,EACN,EAAqB,GACtB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB,
|
|
1
|
+
{"version":3,"file":"getSelectMeta.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/table/funcs/getSelectMeta.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAWzD,wBAA8B,aAAa,CAAC,EAC1C,IAAI,EACJ,UAAU,EACV,GAAG,EACH,OAAO,EACP,MAAM,EACN,EAAqB,GACtB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB,gBAsHA"}
|
|
@@ -30,7 +30,12 @@ export default async function getSelectMeta({ name, startsWith, key, nocache, pa
|
|
|
30
30
|
console.log(`sql select null: ${name}`);
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
const
|
|
33
|
+
const args = [
|
|
34
|
+
limit,
|
|
35
|
+
original.includes("{{parent}}") ? parent : undefined,
|
|
36
|
+
].filter((el) => el !== undefined);
|
|
37
|
+
const original1 = args.length === 2 ? original.replace("'{{parent}}'", "$1") : original;
|
|
38
|
+
const sql = `with c(id,text) as (select * from (${original1})q limit $${args.length > 1 ? 2 : 1}) select * from c`;
|
|
34
39
|
/*= == meta table === */
|
|
35
40
|
const tableNew = original
|
|
36
41
|
.toLowerCase()
|
|
@@ -38,13 +43,13 @@ export default async function getSelectMeta({ name, startsWith, key, nocache, pa
|
|
|
38
43
|
.split(" from ")
|
|
39
44
|
.filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
40
45
|
.map((el) => el.split(/[ )]/)[0].replace(/[\r\n]+/g, ""));
|
|
41
|
-
const dataOrigin = await pg1.query(sql
|
|
42
|
-
const dataOrigin1 = await pg1.query(`${
|
|
46
|
+
const dataOrigin = await pg1.query(sql.replace("limit $2", "limit 0").replace("limit $1", "limit 0"), [parent].filter((el) => el !== undefined));
|
|
47
|
+
const dataOrigin1 = await pg1.query(`${original1} limit 0`, [parent].filter((el) => el !== undefined));
|
|
43
48
|
// const table = getTable(original);
|
|
44
49
|
const count = cls?.count ??
|
|
45
50
|
(await pg1
|
|
46
|
-
.query(`select count(*) from (${
|
|
47
|
-
.then((
|
|
51
|
+
.query(`select count(*) from (${original1})q`, [parent].filter((el) => el !== undefined))
|
|
52
|
+
.then((r) => r?.rows?.[0].count));
|
|
48
53
|
// column name
|
|
49
54
|
const cols = dataOrigin.fields.map((el) => el.name);
|
|
50
55
|
const originalCols = dataOrigin1.fields.map((el) => el.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/access/schema.ts"],"names":[],"mappings":";AAAA,wBAAoB;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/access/schema.ts"],"names":[],"mappings":";AAAA,wBAAoB;AAEpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,CAAC;AAEF,QAAA,MAAM,iBAAiB;;;;;;;;;;;CAQtB,CAAC;AAEF,QAAA,MAAM,gBAAgB;;;;;;;;;;;CAQrB,CAAC;AAEF,QAAA,MAAM,qBAAqB;;;;;;;;;;;CAQ1B,CAAC;AAEF,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4C1B,CAAC;AAEF,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAiCzD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wBAA8B,WAAW,CACvC,EACE,EAAqB,EACrB,OAAO,EACP,IAAI,EACJ,OAAO,EAAE,QAAQ,EACjB,GAAG,EACH,KAAU,EACV,IAAkB,EAClB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAiCzD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wBAA8B,WAAW,CACvC,EACE,EAAqB,EACrB,OAAO,EACP,IAAI,EACJ,OAAO,EAAE,QAAQ,EACjB,GAAG,EACH,KAAU,EACV,IAAkB,EAClB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,KAAK,EAAE,YAAY,gBAsbpB"}
|
|
@@ -229,10 +229,12 @@ export default async function exportTable({ pg = pgClients.client, headers, user
|
|
|
229
229
|
while (+filtered - offset > 0 && !res?.error) {
|
|
230
230
|
try {
|
|
231
231
|
send(`Оброблено: ${offset}/${filtered}`);
|
|
232
|
+
const isSingle = loadTable?.key && id;
|
|
233
|
+
const args = loadTable?.key && id
|
|
234
|
+
? [id, options.limit, offset]
|
|
235
|
+
: [options.limit, offset];
|
|
232
236
|
const { rows = [] } = tableSql || viewSql
|
|
233
|
-
? await pg.query(`select * from (${tableSql || viewSql})q where ${loadTable
|
|
234
|
-
? `${loadTable?.key}::text = '${id}'`
|
|
235
|
-
: "true"} limit ${options.limit} offset ${offset}`)
|
|
237
|
+
? await pg.query(`select * from (${tableSql || viewSql})q where ${isSingle ? `${loadTable.key}::text = $1` : "true"} limit $${isSingle ? 2 : 1} offset $${isSingle ? 3 : 2}`, args)
|
|
236
238
|
: await getData({
|
|
237
239
|
...options,
|
|
238
240
|
query: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resizeAll.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/resizeAll.ts"],"names":[],"mappings":"AA0HA,wBAA8B,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"resizeAll.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/resizeAll.ts"],"names":[],"mappings":"AA0HA,wBAA8B,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAuH3D"}
|
|
@@ -81,11 +81,12 @@ export default async function resizeAll(req, reply) {
|
|
|
81
81
|
const resizeQuality = Math.min(quality, 100);
|
|
82
82
|
const q = `select file_id as id, file_path as relpath from crm.files
|
|
83
83
|
where ext=any($1)
|
|
84
|
-
and ${filepath ? "file_path=$
|
|
85
|
-
and resized is null
|
|
84
|
+
and ${filepath ? "file_path=$3" : "1=1"}
|
|
85
|
+
and resized is null
|
|
86
|
+
limit $2`;
|
|
86
87
|
if (sql)
|
|
87
88
|
return q;
|
|
88
|
-
const { rows = [], rowCount = 0 } = await pg.query(q, [images, filepath].filter(Boolean));
|
|
89
|
+
const { rows = [], rowCount = 0 } = await pg.query(q, [images, Math.min(+limit || 16, 16), filepath].filter(Boolean));
|
|
89
90
|
if (rowCount === 0) {
|
|
90
91
|
return reply.status(200).send("nothing to resize");
|
|
91
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/index.ts"],"names":[],"mappings":"AAoBA,iBAAS,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,GAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/index.ts"],"names":[],"mappings":"AAoBA,iBAAS,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,GAAQ,QAqCtC;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -7,7 +7,7 @@ import download from "./controllers/download.js";
|
|
|
7
7
|
import exportTable from "./controllers/export.js";
|
|
8
8
|
import uploadImage from "./controllers/uploadImage.js";
|
|
9
9
|
import deleteFileAPI from "./controllers/delete.js";
|
|
10
|
-
import { resizeSchema } from "./schema.js";
|
|
10
|
+
import { resizeSchema, exportSchema } from "./schema.js";
|
|
11
11
|
const tags = ["core", "file"];
|
|
12
12
|
const { uploadPolicy = "L1" } = config;
|
|
13
13
|
const publicParams = { config: { tags, policy: "L0" } };
|
|
@@ -15,7 +15,9 @@ const privateParams = { config: { tags, policy: uploadPolicy } };
|
|
|
15
15
|
function plugin(app, opt = {}) {
|
|
16
16
|
app.get("/files/*", publicParams, files);
|
|
17
17
|
if (!app.hasRoute({ method: "GET", url: "/file/resize" })) {
|
|
18
|
-
app.
|
|
18
|
+
app.route({
|
|
19
|
+
method: "GET",
|
|
20
|
+
url: "/file/resize",
|
|
19
21
|
config: {
|
|
20
22
|
...publicParams,
|
|
21
23
|
rateLimit: config.rateLimit
|
|
@@ -26,13 +28,26 @@ function plugin(app, opt = {}) {
|
|
|
26
28
|
: undefined,
|
|
27
29
|
},
|
|
28
30
|
schema: resizeSchema,
|
|
29
|
-
|
|
31
|
+
handler: resize,
|
|
32
|
+
});
|
|
30
33
|
}
|
|
31
|
-
app.
|
|
34
|
+
app.route({
|
|
35
|
+
method: "GET",
|
|
36
|
+
url: "/api/resize-all",
|
|
37
|
+
config: { tags, role: "admin" },
|
|
38
|
+
schema: resizeSchema,
|
|
39
|
+
handler: resizeAll,
|
|
40
|
+
});
|
|
32
41
|
app.post("/file/upload/*", privateParams, upload);
|
|
33
42
|
app.post("/file/upload-image/*", privateParams, uploadImage);
|
|
34
43
|
app.get("/file/download/*", publicParams, download);
|
|
35
44
|
app.get("/file/delete/*", publicParams, deleteFileAPI);
|
|
36
|
-
app.
|
|
45
|
+
app.route({
|
|
46
|
+
method: "GET",
|
|
47
|
+
url: "/api/export",
|
|
48
|
+
...publicParams,
|
|
49
|
+
schema: exportSchema,
|
|
50
|
+
handler: exportTable,
|
|
51
|
+
});
|
|
37
52
|
}
|
|
38
53
|
export default plugin;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare const resizeSchema: {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
querystring: {
|
|
3
|
+
type: string;
|
|
4
|
+
properties: {
|
|
5
5
|
filepath: {
|
|
6
6
|
type: string;
|
|
7
7
|
};
|
|
@@ -27,7 +27,30 @@ declare const resizeSchema: {
|
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
|
+
declare const exportSchema: {
|
|
31
|
+
querystring: {
|
|
32
|
+
type: string;
|
|
33
|
+
properties: {
|
|
34
|
+
limit: {
|
|
35
|
+
type: string;
|
|
36
|
+
minimum: number;
|
|
37
|
+
};
|
|
38
|
+
batchLimit: {
|
|
39
|
+
type: string;
|
|
40
|
+
minimum: number;
|
|
41
|
+
};
|
|
42
|
+
page: {
|
|
43
|
+
type: string;
|
|
44
|
+
minimum: number;
|
|
45
|
+
};
|
|
46
|
+
key: {
|
|
47
|
+
type: string;
|
|
48
|
+
pattern: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
30
53
|
declare const _default: null;
|
|
31
54
|
export default _default;
|
|
32
|
-
export { resizeSchema };
|
|
55
|
+
export { resizeSchema, exportSchema };
|
|
33
56
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcjB,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;CAUjB,CAAC;;AAEF,wBAAoB;AAEpB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
const resizeSchema = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
filepath: { type:
|
|
6
|
-
quality: { type:
|
|
7
|
-
size: {
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
querystring: {
|
|
3
|
+
type: "object",
|
|
4
|
+
properties: {
|
|
5
|
+
filepath: { type: "string" },
|
|
6
|
+
quality: { type: "number", exclusiveMinimum: 0, maximum: 100 },
|
|
7
|
+
size: {
|
|
8
|
+
type: "string",
|
|
9
|
+
pattern: "^((\\d{1,4})x(\\d{1,4})|(\\d{1,4})x|x(\\d{1,4}))$",
|
|
10
|
+
},
|
|
11
|
+
w: { type: "number", minimum: 1, maximum: 2048 },
|
|
12
|
+
h: { type: "number", minimum: 1, maximum: 2048 },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const exportSchema = {
|
|
17
|
+
querystring: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
limit: { type: "number", minimum: 1 },
|
|
21
|
+
batchLimit: { type: "number", minimum: 1 },
|
|
22
|
+
page: { type: "number", minimum: 1 },
|
|
23
|
+
key: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
10
24
|
},
|
|
11
25
|
},
|
|
12
26
|
};
|
|
13
27
|
export default null;
|
|
14
|
-
export { resizeSchema };
|
|
28
|
+
export { resizeSchema, exportSchema };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/search.ts"],"names":[],"mappings":"AAkJA,wBAA8B,MAAM,CAAC,EACnC,EAAqB,EACrB,KAAU,GACX,EAAE,GAAG;;;;;;GAmCL"}
|
|
@@ -11,7 +11,7 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
13
|
const { table, columns, meta } = loadTable;
|
|
14
|
-
const { pk, view } = await getMeta({ pg, table });
|
|
14
|
+
const { pk, view } = (await getMeta({ pg, table }).catch((err) => null)) || {};
|
|
15
15
|
if (!pk && !view) {
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
@@ -20,14 +20,19 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
20
20
|
const order = cols.includes(orderColumn) && orderColumn?.length
|
|
21
21
|
? `order by ${orderColumn} ${query.desc || orderDir === "desc" ? "desc" : ""}`
|
|
22
22
|
: "";
|
|
23
|
+
const args = [];
|
|
23
24
|
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
24
|
-
|
|
25
|
-
const offset = query.page && query.page > 0 ?
|
|
25
|
+
args.push(limit);
|
|
26
|
+
const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
|
|
27
|
+
args.push(offset);
|
|
28
|
+
if (meta?.search && query.key) {
|
|
29
|
+
args.push(`%${query.key}%`);
|
|
30
|
+
}
|
|
26
31
|
const search1 = meta?.search && query.key
|
|
27
32
|
? `(${meta?.search
|
|
28
33
|
.concat(meta?.title ? `,${meta?.title}` : "")
|
|
29
34
|
.split(",")
|
|
30
|
-
.map((el) => `${el}::text ilike
|
|
35
|
+
.map((el) => `${el}::text ilike $3`)
|
|
31
36
|
.join(" or ")})`
|
|
32
37
|
: "false";
|
|
33
38
|
const where = [!pk ? "false" : "true", loadTable.query, search1].filter(Boolean);
|
|
@@ -40,23 +45,26 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
40
45
|
meta?.title ? `${meta.title} as title` : "",
|
|
41
46
|
]
|
|
42
47
|
.filter((el) => el)
|
|
43
|
-
.join(",")} from ${table} t ${sqlTable} where ${where.join(" and ") || "true"} ${order} $
|
|
48
|
+
.join(",")} from ${table} t ${sqlTable} where ${where.join(" and ") || "true"} ${order} limit $1 offset $2`;
|
|
44
49
|
if (query.sql) {
|
|
45
50
|
res.sql.push(q);
|
|
46
51
|
return null;
|
|
47
52
|
}
|
|
48
|
-
const rows = await pg.query(q).then((
|
|
53
|
+
const rows = await pg.query(q, args).then((r) => r.rows || []);
|
|
49
54
|
const filtered = pg.queryCache
|
|
50
55
|
? await pg
|
|
51
|
-
.queryCache(`select count(*) from ${table} t ${sqlTable} where ${where.join(" and ") || "true"}
|
|
52
|
-
|
|
56
|
+
.queryCache(`select count(*) from ${table} t ${sqlTable} where ${where.join(" and ").replace(/\$3/g, "$1") || "true"}`, {
|
|
57
|
+
args: [meta?.search && query.key ? query.key : undefined].filter(Boolean),
|
|
58
|
+
table,
|
|
59
|
+
})
|
|
60
|
+
.then((r) => +(r?.rows[0]?.count || 0))
|
|
53
61
|
: 0;
|
|
54
62
|
const total = pg.queryCache
|
|
55
63
|
? await pg
|
|
56
64
|
.queryCache(`select count(*) from ${table}`)
|
|
57
|
-
.then((
|
|
65
|
+
.then((r) => +(r?.rows[0]?.count || 0))
|
|
58
66
|
: 0;
|
|
59
|
-
await metaFormat({ rows, table: tableName });
|
|
67
|
+
await metaFormat({ rows, table: tableName }, pg);
|
|
60
68
|
res.total += +total;
|
|
61
69
|
res.filtered += +filtered;
|
|
62
70
|
rows.forEach((row) => {
|
|
@@ -83,7 +91,7 @@ export default async function search({ pg = pgClients.client, query = {}, }) {
|
|
|
83
91
|
total: 0,
|
|
84
92
|
filtered: 0,
|
|
85
93
|
};
|
|
86
|
-
const maxLimit = Math.min(100, query.limit ||
|
|
94
|
+
const maxLimit = Math.min(100, +query.limit || 16);
|
|
87
95
|
await sequence(tables, {
|
|
88
96
|
pg,
|
|
89
97
|
query,
|
|
@@ -68,7 +68,7 @@ export async function getTableColumnMeta({ table, template, column, selectName,
|
|
|
68
68
|
export default async function suggest(req) {
|
|
69
69
|
const time = Date.now();
|
|
70
70
|
const { params, user, query = {}, pg: pg1 = pgClients.client } = req;
|
|
71
|
-
const { lang = "ua", parent
|
|
71
|
+
const { lang = "ua", parent } = query;
|
|
72
72
|
const debugMode = config.local ||
|
|
73
73
|
user?.user_type?.includes?.("admin") ||
|
|
74
74
|
process.env.NODE_ENV === "test" ||
|
|
@@ -20,5 +20,5 @@ export default function dataAPI({ pg, params, table, id, headers, query, user, c
|
|
|
20
20
|
accessQuery?: string;
|
|
21
21
|
columns?: string[];
|
|
22
22
|
isExport?: boolean;
|
|
23
|
-
},
|
|
23
|
+
}, reply?: FastifyReply, called?: any): Promise<any>;
|
|
24
24
|
//# sourceMappingURL=getData.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,
|
|
1
|
+
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,KAAK,CAAC,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,GAAG,gBA64Bb"}
|
|
@@ -54,13 +54,11 @@ function getOrder(queryOrder, queryDesc, defaultOrder, columnList, sqlColumns, i
|
|
|
54
54
|
const checkInline = {};
|
|
55
55
|
const maxLimit = 100;
|
|
56
56
|
const defaultLimit = 20;
|
|
57
|
-
export default async function dataAPI({ pg = pgClients.client, params, table, id, headers = {}, query = {}, user = {}, contextQuery, searchColumn, sufix = true, filterList, actions: actionsParam, accessQuery: accessQueryParam, columns: columnsParam, isExport = false, },
|
|
57
|
+
export default async function dataAPI({ pg = pgClients.client, params, table, id, headers = {}, query = {}, user = {}, contextQuery, searchColumn, sufix = true, filterList, actions: actionsParam, accessQuery: accessQueryParam, columns: columnsParam, isExport = false, }, reply, called) {
|
|
58
58
|
const time = Date.now();
|
|
59
59
|
const timeArr = [Date.now()];
|
|
60
60
|
const { uid } = user;
|
|
61
|
-
const reply = reply1 || mockReply;
|
|
62
61
|
const method = "GET";
|
|
63
|
-
const checkQuery = (item) => user?.user_type === "superadmin" ? !item.includes("{{uid}}") : true;
|
|
64
62
|
const paramsTable = params?.table || table;
|
|
65
63
|
if (!paramsTable) {
|
|
66
64
|
throw BadRequestError("not enough params: table");
|
|
@@ -210,14 +208,14 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
210
208
|
!el.inline &&
|
|
211
209
|
el?.sql?.replace &&
|
|
212
210
|
!(isExport && el.export === false))
|
|
213
|
-
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ${el.name || `t${i}`} on 1=1 `)
|
|
211
|
+
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ${el.name || `t${i}`} on 1=1 `)
|
|
214
212
|
?.join("") || "";
|
|
215
213
|
const cardSqlFiltered = objectId
|
|
216
214
|
? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []
|
|
217
215
|
: [];
|
|
218
216
|
const cardSqlTable = cardSqlFiltered.length
|
|
219
217
|
? cardSqlFiltered
|
|
220
|
-
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ct${i} on 1=1 `)
|
|
218
|
+
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ct${i} on 1=1 `)
|
|
221
219
|
.join("\n") || ""
|
|
222
220
|
: "";
|
|
223
221
|
const sqlInline = loadTable?.sql
|
|
@@ -277,21 +275,40 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
277
275
|
const keyQuery = query?.key && (loadTable?.key || tokenData?.key) && !objectId
|
|
278
276
|
? `${loadTable?.key || tokenData?.key}=$1`
|
|
279
277
|
: null;
|
|
278
|
+
const idx = {};
|
|
279
|
+
const args = (objectId ? [objectId] : null) ||
|
|
280
|
+
(query?.key && loadTable.key ? [query.key] : []);
|
|
281
|
+
if (args[0]) {
|
|
282
|
+
Object.assign(idx, { id: 1 });
|
|
283
|
+
}
|
|
284
|
+
const isSingle = !!idx.id;
|
|
280
285
|
const limit = (called
|
|
281
286
|
? query?.limit || defaultLimit
|
|
282
287
|
: Math.min(maxLimit, +(query?.limit || defaultLimit))) || defaultLimit;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
288
|
+
args.push(limit);
|
|
289
|
+
Object.assign(idx, { limit: idx.id ? 2 : 1 });
|
|
290
|
+
const offset = query?.page && query?.page > 0 && !objectId ? (query?.page - 1) * limit : 0;
|
|
291
|
+
args.push(offset);
|
|
292
|
+
Object.assign(idx, { offset: idx.id ? 3 : 2 });
|
|
286
293
|
const order = getOrder(query?.order, query?.desc, loadTable?.order, columnList, loadTable?.sqlColumns, !!called);
|
|
294
|
+
const isSearchable = Array.isArray(loadTable?.meta?.search) &&
|
|
295
|
+
loadTable.meta.search.length &&
|
|
296
|
+
query?.search &&
|
|
297
|
+
!isSingle;
|
|
298
|
+
if (isSearchable) {
|
|
299
|
+
args.push(`%${query.search.replace(/%/g, "\\%")}%`);
|
|
300
|
+
Object.assign(idx, { search: Object.keys(idx).length + 1 });
|
|
301
|
+
}
|
|
302
|
+
if (meta?.bbox && query?.polyline) {
|
|
303
|
+
args.push(query.polyline);
|
|
304
|
+
Object.assign(idx, { polyline: Object.keys(idx).length + 1 });
|
|
305
|
+
}
|
|
287
306
|
if (config.trace)
|
|
288
307
|
console.log(order);
|
|
289
|
-
const search =
|
|
308
|
+
const search = isSearchable
|
|
290
309
|
? `(${loadTable?.meta?.search
|
|
291
310
|
?.split(",")
|
|
292
|
-
?.map((el) => `${el} ilike
|
|
293
|
-
.replace(/%/g, "\\%")
|
|
294
|
-
.replace(/'/g, "''")}%'`)
|
|
311
|
+
?.map((el) => `${el} ilike $${idx.search}`)
|
|
295
312
|
.join(" or ")})`
|
|
296
313
|
: null;
|
|
297
314
|
const queryBbox = query?.bbox
|
|
@@ -301,7 +318,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
301
318
|
?.map((el) => el - 0)
|
|
302
319
|
: [];
|
|
303
320
|
const queryPolyline = meta?.bbox && query?.polyline
|
|
304
|
-
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline(
|
|
321
|
+
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline($${idx.polyline})),${meta.bbox})`
|
|
305
322
|
: undefined;
|
|
306
323
|
const bbox = meta?.bbox && queryBbox.filter((el) => !Number.isNaN(el))?.length === 4
|
|
307
324
|
? `${meta.bbox} && 'box(${queryBbox[0]} ${queryBbox[1]},${queryBbox[2]} ${queryBbox[3]})'::box2d `
|
|
@@ -318,7 +335,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
318
335
|
? await handlebars.compile(params?.query)({ user, uid })
|
|
319
336
|
: undefined;
|
|
320
337
|
const where = [
|
|
321
|
-
objectId ? ` "${pk}" =
|
|
338
|
+
objectId ? ` "${pk}" = $${idx.id}` : null,
|
|
322
339
|
keyQuery,
|
|
323
340
|
loadTable?.query,
|
|
324
341
|
tokenData?.query,
|
|
@@ -330,40 +347,36 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
330
347
|
queryPolyline,
|
|
331
348
|
interfaceQuery,
|
|
332
349
|
interfaceQuery1,
|
|
333
|
-
]
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
: columnsParam || sqlColumns || cols || "*"}
|
|
340
|
-
${metaCols}
|
|
341
|
-
${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry").length && !columnsParam
|
|
350
|
+
].filter(Boolean);
|
|
351
|
+
const q1 = `select ${pk ? `"${pk}" as id,` : ""}
|
|
352
|
+
${objectId || query?.key ? "*" : columnsParam || sqlColumns || cols || "*"}
|
|
353
|
+
${metaCols}
|
|
354
|
+
${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
355
|
+
.length && !columnsParam
|
|
342
356
|
? `,${dbColumns
|
|
343
357
|
.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
344
358
|
.map((el) => `st_asgeojson("${el.name.replace(/'/g, "''")}")::json as "${el.name.replace(/'/g, "''")}"`)
|
|
345
359
|
.join(",")}`
|
|
346
360
|
: ""}
|
|
347
|
-
|
|
361
|
+
from (select * ${sql
|
|
348
362
|
?.filter((el) => el.inline && !(isExport && el.export === false))
|
|
349
363
|
.map((el) => `,(${el.sql})`)
|
|
350
364
|
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable} ) t
|
|
351
365
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
366
|
+
${objectId ? cardSqlTable : ""}
|
|
367
|
+
where ${where.join(" and ") || "true"}
|
|
368
|
+
${order} limit $${idx.limit} offset $${idx.offset}`;
|
|
369
|
+
if (q1.includes("{{uid}}")) {
|
|
370
|
+
args.push(uid || "");
|
|
371
|
+
Object.assign(idx, { uid: Object.keys(idx).length + 1 });
|
|
372
|
+
}
|
|
373
|
+
const q = q1.replace(/{{uid}}/g, `$${idx.uid}`);
|
|
355
374
|
if (config.trace)
|
|
356
375
|
console.log(q);
|
|
357
376
|
if (query?.sql === "1") {
|
|
358
377
|
return q;
|
|
359
378
|
}
|
|
360
|
-
const
|
|
361
|
-
.query(q, (objectId ? [objectId] : null) ||
|
|
362
|
-
(query?.key && loadTable.key ? [query?.key] : []))
|
|
363
|
-
.catch((err) => {
|
|
364
|
-
console.error(err.toString());
|
|
365
|
-
throw err;
|
|
366
|
-
});
|
|
379
|
+
const rows = await pg.query(q, args).then((r) => r.rows || []);
|
|
367
380
|
if (!rows.length &&
|
|
368
381
|
headers?.referer?.includes?.("/card/") &&
|
|
369
382
|
headers?.referer?.includes?.(templateName)) {
|
|
@@ -395,17 +408,38 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
395
408
|
});
|
|
396
409
|
});
|
|
397
410
|
}
|
|
411
|
+
const idx1 = {};
|
|
412
|
+
const args1 = [];
|
|
413
|
+
if (idx.search) {
|
|
414
|
+
args1.push(args[idx.search - 1]);
|
|
415
|
+
Object.assign(idx1, { search: Object.keys(idx1).length + 1 });
|
|
416
|
+
}
|
|
417
|
+
if (idx.uid) {
|
|
418
|
+
args1.push(args[idx.uid - 1]);
|
|
419
|
+
Object.assign(idx1, { uid: Object.keys(idx1).length + 1 });
|
|
420
|
+
}
|
|
421
|
+
if (idx.polyline) {
|
|
422
|
+
args1.push(args[idx.polyline - 1]);
|
|
423
|
+
Object.assign(idx1, { polyline: Object.keys(idx1).length + 1 });
|
|
424
|
+
}
|
|
425
|
+
const search1 = idx.search
|
|
426
|
+
? `(${loadTable.meta.search
|
|
427
|
+
.split(",")
|
|
428
|
+
.map((el) => `${el} ilike $${idx1.search}`)
|
|
429
|
+
.join(" or ")})`
|
|
430
|
+
: null;
|
|
431
|
+
const queryPolyline1 = idx.polyline
|
|
432
|
+
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline($${idx1.polyline})),${meta.bbox})`
|
|
433
|
+
: undefined;
|
|
398
434
|
const filterWhere = [
|
|
399
435
|
fData.q,
|
|
400
|
-
|
|
436
|
+
search1,
|
|
401
437
|
bbox,
|
|
402
|
-
|
|
438
|
+
queryPolyline1,
|
|
403
439
|
interfaceQuery,
|
|
404
440
|
loadTable?.query,
|
|
405
441
|
tokenData?.query,
|
|
406
|
-
]
|
|
407
|
-
.filter(Boolean)
|
|
408
|
-
.filter((el) => checkQuery(el));
|
|
442
|
+
].filter(Boolean);
|
|
409
443
|
const aggColumns = columns
|
|
410
444
|
.filter((el) => el.agg)
|
|
411
445
|
.reduce((acc, curr) => Object.assign(acc, { [curr.name]: curr.agg }), {});
|
|
@@ -416,21 +450,20 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
416
450
|
}))
|
|
417
451
|
.filter((el) => ["numeric", "double precision"].includes(el.type) && aggColumns[el.name]);
|
|
418
452
|
const qCount = `select
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
453
|
+
count(*)::int as total,
|
|
454
|
+
count(*) FILTER(WHERE ${filterWhere.join(" and ") || "true"})::int as filtered
|
|
455
|
+
${aggregates.length
|
|
422
456
|
? `,${aggregates
|
|
423
457
|
.map((el) => `${aggColumns[el.name]}(${el.name}) FILTER(WHERE ${filterWhere.join(" and ") || "true"}) as ${el.name}`)
|
|
424
458
|
.join(",")}`
|
|
425
459
|
: ""}
|
|
426
|
-
|
|
460
|
+
from (select * ${sql
|
|
427
461
|
?.filter((el) => el.inline)
|
|
428
462
|
.map((el) => `,(${el.sql})`)
|
|
429
463
|
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable})t
|
|
430
|
-
|
|
464
|
+
where ${[loadTable?.query, tokenData?.query, accessQuery, contextQuery]
|
|
431
465
|
.filter(Boolean)
|
|
432
|
-
.
|
|
433
|
-
.join(" and ") || "true"} `.replace(/{{uid}}/g, uid);
|
|
466
|
+
.join(" and ") || "true"} `.replace(/{{uid}}/g, `$${idx1.uid}`);
|
|
434
467
|
if (query?.sql === "2") {
|
|
435
468
|
return qCount;
|
|
436
469
|
}
|
|
@@ -438,6 +471,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
438
471
|
? { total: rows.length, filtered: rows.length }
|
|
439
472
|
: await pg
|
|
440
473
|
.queryCache?.(qCount, {
|
|
474
|
+
args: args1,
|
|
441
475
|
table: loadTable?.table || tokenData?.table,
|
|
442
476
|
time: 5,
|
|
443
477
|
})
|
|
@@ -32,7 +32,8 @@ function plugin(app, opt = {}) {
|
|
|
32
32
|
},
|
|
33
33
|
schema: suggestSchema,
|
|
34
34
|
}, suggest);
|
|
35
|
-
app.get("/data/:table/:id?", { config: { tags, policy }, schema: tableSchema },
|
|
35
|
+
app.get("/data/:table/:id?", { config: { tags, policy, allowSql: true }, schema: tableSchema }, // query.polyline support w/ allowSql
|
|
36
|
+
data);
|
|
36
37
|
app.get("/table-data/:table", { config: { tags, auth: "creds", policy: "L2" }, schema: tableDataSchema }, data);
|
|
37
38
|
app.get("/table-data/:table/:id", { config: { tags, policy }, schema: tableDataIdSchema }, cardData);
|
|
38
39
|
app.get("/data-info/:id?", { config: { tags, policy }, schema: tableSchema }, dataInfo);
|
|
@@ -4,11 +4,11 @@ declare const tableDataSchema: {
|
|
|
4
4
|
querystring: {
|
|
5
5
|
limit: {
|
|
6
6
|
type: string;
|
|
7
|
-
|
|
7
|
+
minimum: number;
|
|
8
8
|
};
|
|
9
9
|
page: {
|
|
10
10
|
type: string;
|
|
11
|
-
|
|
11
|
+
minimum: number;
|
|
12
12
|
};
|
|
13
13
|
order: {
|
|
14
14
|
type: string;
|
|
@@ -36,7 +36,6 @@ declare const tableDataSchema: {
|
|
|
36
36
|
};
|
|
37
37
|
sql: {
|
|
38
38
|
type: string;
|
|
39
|
-
pattern: string;
|
|
40
39
|
};
|
|
41
40
|
};
|
|
42
41
|
params: {
|
|
@@ -57,11 +56,11 @@ declare const tableSchema: {
|
|
|
57
56
|
querystring: {
|
|
58
57
|
limit: {
|
|
59
58
|
type: string;
|
|
60
|
-
|
|
59
|
+
minimum: number;
|
|
61
60
|
};
|
|
62
61
|
page: {
|
|
63
62
|
type: string;
|
|
64
|
-
|
|
63
|
+
minimum: number;
|
|
65
64
|
};
|
|
66
65
|
order: {
|
|
67
66
|
type: string;
|
|
@@ -85,7 +84,6 @@ declare const tableSchema: {
|
|
|
85
84
|
};
|
|
86
85
|
sql: {
|
|
87
86
|
type: string;
|
|
88
|
-
pattern: string;
|
|
89
87
|
};
|
|
90
88
|
};
|
|
91
89
|
params: {
|
|
@@ -106,11 +104,11 @@ declare const searchSchema: {
|
|
|
106
104
|
querystring: {
|
|
107
105
|
page: {
|
|
108
106
|
type: string;
|
|
109
|
-
|
|
107
|
+
minimum: number;
|
|
110
108
|
};
|
|
111
109
|
limit: {
|
|
112
110
|
type: string;
|
|
113
|
-
|
|
111
|
+
minimum: number;
|
|
114
112
|
};
|
|
115
113
|
order: {
|
|
116
114
|
type: string;
|
|
@@ -161,11 +159,9 @@ declare const suggestSchema: {
|
|
|
161
159
|
};
|
|
162
160
|
sql: {
|
|
163
161
|
type: string;
|
|
164
|
-
pattern: string;
|
|
165
162
|
};
|
|
166
163
|
count: {
|
|
167
164
|
type: string;
|
|
168
|
-
pattern: string;
|
|
169
165
|
};
|
|
170
166
|
};
|
|
171
167
|
params: {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/table/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/table/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBhB,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAajB,CAAC;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBlB,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;;;CAQf,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;CAOjB,CAAC;AAEF,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAUtB,CAAC;AAEF,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;CAQtB,CAAC;AAEF,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,iBAAiB,GAClB,CAAC"}
|
|
@@ -1,76 +1,76 @@
|
|
|
1
1
|
const tableDataSchema = {
|
|
2
|
-
type:
|
|
2
|
+
type: "object",
|
|
3
3
|
properties: {
|
|
4
4
|
querystring: {
|
|
5
|
-
limit: { type:
|
|
6
|
-
page: { type:
|
|
5
|
+
limit: { type: "number", minimum: 1 },
|
|
6
|
+
page: { type: "number", minimum: 1 },
|
|
7
7
|
// filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
8
8
|
// search: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
9
|
-
order: { type:
|
|
10
|
-
desc: { type:
|
|
11
|
-
state: { type:
|
|
12
|
-
custom: { type:
|
|
13
|
-
bbox: { type:
|
|
14
|
-
polyline: { type:
|
|
9
|
+
order: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
10
|
+
desc: { type: "string", pattern: "^(\\d+)$" },
|
|
11
|
+
state: { type: "string", pattern: "^([\\d\\w._-]+)$" },
|
|
12
|
+
custom: { type: "string", pattern: "^([\\d\\w._-]+)$" },
|
|
13
|
+
bbox: { type: "string", pattern: "^([\\d\\s,.-]+)$" },
|
|
14
|
+
polyline: { type: "string", pattern: "^([\\d\\w|@{}~_`]+)$" },
|
|
15
15
|
// key: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
16
|
-
sql: { type:
|
|
16
|
+
sql: { type: "number" },
|
|
17
17
|
},
|
|
18
18
|
params: {
|
|
19
|
-
id: { type:
|
|
20
|
-
table: { type:
|
|
19
|
+
id: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
20
|
+
table: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
};
|
|
24
24
|
const tableSchema = {
|
|
25
|
-
type:
|
|
25
|
+
type: "object",
|
|
26
26
|
properties: {
|
|
27
27
|
querystring: {
|
|
28
|
-
limit: { type:
|
|
29
|
-
page: { type:
|
|
28
|
+
limit: { type: "number", minimum: 1 },
|
|
29
|
+
page: { type: "number", minimum: 1 },
|
|
30
30
|
// filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
31
31
|
// search: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
32
|
-
order: { type:
|
|
33
|
-
desc: { type:
|
|
32
|
+
order: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
33
|
+
desc: { type: "string", pattern: "^(\\d+)$" },
|
|
34
34
|
// state: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
35
35
|
// custom: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
36
|
-
bbox: { type:
|
|
36
|
+
bbox: { type: "string", pattern: "^([\\d\\s,.-]+)$" },
|
|
37
37
|
// polyline: { type: 'string', pattern: '^([\\d\\w\\|@\\/\\{\\}~_`]+)$' },
|
|
38
|
-
key: { type:
|
|
39
|
-
uid: { type:
|
|
40
|
-
sql: { type:
|
|
38
|
+
key: { type: "string", pattern: "^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$" },
|
|
39
|
+
uid: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
40
|
+
sql: { type: "number" },
|
|
41
41
|
},
|
|
42
42
|
params: {
|
|
43
|
-
id: { type:
|
|
44
|
-
table: { type:
|
|
43
|
+
id: { type: "string", pattern: "^([\\d\\w]+)$" },
|
|
44
|
+
table: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
45
45
|
},
|
|
46
46
|
},
|
|
47
47
|
};
|
|
48
48
|
const searchSchema = {
|
|
49
|
-
type:
|
|
49
|
+
type: "object",
|
|
50
50
|
properties: {
|
|
51
51
|
querystring: {
|
|
52
|
-
page: { type:
|
|
53
|
-
limit: { type:
|
|
54
|
-
order: { type:
|
|
55
|
-
desc: { type:
|
|
56
|
-
key: { type:
|
|
57
|
-
table: { type:
|
|
58
|
-
sql: { type:
|
|
52
|
+
page: { type: "number", minimum: 1 },
|
|
53
|
+
limit: { type: "number", minimum: 1 },
|
|
54
|
+
order: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
55
|
+
desc: { type: "string", pattern: "^(\\d+)$" },
|
|
56
|
+
key: { type: "string", pattern: "^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$" },
|
|
57
|
+
table: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
58
|
+
sql: { type: "string", pattern: "^(\\d)$" },
|
|
59
59
|
},
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
62
|
const suggestSchema = {
|
|
63
|
-
type:
|
|
63
|
+
type: "object",
|
|
64
64
|
properties: {
|
|
65
65
|
querystring: {
|
|
66
|
-
lang: { type:
|
|
67
|
-
parent: { type:
|
|
68
|
-
sel: { type:
|
|
69
|
-
name: { type:
|
|
66
|
+
lang: { type: "string", pattern: "^([\\w]+)$" },
|
|
67
|
+
parent: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
68
|
+
sel: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
69
|
+
name: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
70
70
|
// key: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
71
|
-
val: { type:
|
|
72
|
-
sql: { type:
|
|
73
|
-
count: { type:
|
|
71
|
+
val: { type: "string", pattern: "([\\d\\w]+)$" },
|
|
72
|
+
sql: { type: "number" },
|
|
73
|
+
count: { type: "number" },
|
|
74
74
|
},
|
|
75
75
|
params: {
|
|
76
76
|
// data: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
@@ -78,39 +78,39 @@ const suggestSchema = {
|
|
|
78
78
|
},
|
|
79
79
|
};
|
|
80
80
|
const formSchema = {
|
|
81
|
-
type:
|
|
81
|
+
type: "object",
|
|
82
82
|
properties: {
|
|
83
83
|
params: {
|
|
84
|
-
name: { type:
|
|
85
|
-
id: { type:
|
|
84
|
+
name: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
85
|
+
id: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
88
|
};
|
|
89
89
|
const filterSchema = {
|
|
90
|
-
type:
|
|
90
|
+
type: "object",
|
|
91
91
|
properties: {
|
|
92
92
|
params: {
|
|
93
|
-
table: { type:
|
|
93
|
+
table: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
94
94
|
},
|
|
95
95
|
},
|
|
96
96
|
};
|
|
97
97
|
const cardTabDataSchema = {
|
|
98
|
-
type:
|
|
98
|
+
type: "object",
|
|
99
99
|
properties: {
|
|
100
100
|
querystring: {
|
|
101
|
-
sql: { type:
|
|
101
|
+
sql: { type: "string", pattern: "^(\\d)$" },
|
|
102
102
|
},
|
|
103
103
|
params: {
|
|
104
|
-
token: { type:
|
|
104
|
+
token: { type: "string", pattern: "^([\\d\\w]+)$" },
|
|
105
105
|
},
|
|
106
106
|
},
|
|
107
107
|
};
|
|
108
108
|
const tableDataIdSchema = {
|
|
109
|
-
type:
|
|
109
|
+
type: "object",
|
|
110
110
|
properties: {
|
|
111
111
|
params: {
|
|
112
|
-
id: { type:
|
|
113
|
-
name: { type:
|
|
112
|
+
id: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
113
|
+
name: { type: "string", pattern: "^([\\d\\w._-]+)$" },
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
116
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/templates/index.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,GAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/templates/index.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAE,GAAQ,QAQpD"}
|
|
@@ -3,5 +3,11 @@ import { getTemplateSchema } from "./schema.js";
|
|
|
3
3
|
const policy = "L0";
|
|
4
4
|
const tags = ["core", "templates"];
|
|
5
5
|
export default function route(app, opt = {}) {
|
|
6
|
-
app.
|
|
6
|
+
app.route({
|
|
7
|
+
method: "GET",
|
|
8
|
+
url: "/template/:type/:name",
|
|
9
|
+
config: { tags, policy },
|
|
10
|
+
schema: getTemplateSchema,
|
|
11
|
+
handler: getTemplateApi,
|
|
12
|
+
});
|
|
7
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/templates/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB;;;;;;;;;;CAQtB,CAAC;;AAEF,wBAAoB;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/templates/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB;;;;;;;;;;CAQtB,CAAC;;AAEF,wBAAoB;AAEpB,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const getTemplateSchema = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
name: { type:
|
|
2
|
+
params: {
|
|
3
|
+
type: "object",
|
|
4
|
+
properties: {
|
|
5
|
+
name: { type: "string", pattern: "^([\\d\\w._-]+)$" },
|
|
6
6
|
// type: { type: 'string' },
|
|
7
7
|
},
|
|
8
8
|
},
|