@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.
Files changed (33) hide show
  1. package/dist/server/migrations/users.sql +11 -1
  2. package/dist/server/plugins/crud/funcs/utils/logChanges.d.ts.map +1 -1
  3. package/dist/server/plugins/crud/funcs/utils/logChanges.js +5 -2
  4. package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
  5. package/dist/server/plugins/policy/funcs/checkPolicy.js +4 -1
  6. package/dist/server/plugins/table/funcs/getSelectMeta.d.ts.map +1 -1
  7. package/dist/server/plugins/table/funcs/getSelectMeta.js +10 -5
  8. package/dist/server/routes/access/schema.d.ts.map +1 -1
  9. package/dist/server/routes/file/controllers/export.d.ts.map +1 -1
  10. package/dist/server/routes/file/controllers/export.js +5 -3
  11. package/dist/server/routes/file/controllers/resizeAll.d.ts.map +1 -1
  12. package/dist/server/routes/file/controllers/resizeAll.js +4 -3
  13. package/dist/server/routes/file/index.d.ts.map +1 -1
  14. package/dist/server/routes/file/index.js +20 -5
  15. package/dist/server/routes/file/schema.d.ts +27 -4
  16. package/dist/server/routes/file/schema.d.ts.map +1 -1
  17. package/dist/server/routes/file/schema.js +23 -9
  18. package/dist/server/routes/table/controllers/search.d.ts.map +1 -1
  19. package/dist/server/routes/table/controllers/search.js +19 -11
  20. package/dist/server/routes/table/controllers/suggest.js +1 -1
  21. package/dist/server/routes/table/functions/getData.d.ts +1 -1
  22. package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
  23. package/dist/server/routes/table/functions/getData.js +80 -46
  24. package/dist/server/routes/table/index.js +2 -1
  25. package/dist/server/routes/table/schema.d.ts +6 -10
  26. package/dist/server/routes/table/schema.d.ts.map +1 -1
  27. package/dist/server/routes/table/schema.js +50 -50
  28. package/dist/server/routes/templates/index.d.ts.map +1 -1
  29. package/dist/server/routes/templates/index.js +7 -1
  30. package/dist/server/routes/templates/schema.d.ts +3 -3
  31. package/dist/server/routes/templates/schema.d.ts.map +1 -1
  32. package/dist/server/routes/templates/schema.js +4 -4
  33. 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
- CREATE OR REPLACE FUNCTION admin.crypt(text, text) RETURNS text AS '$libdir/pgcrypto', 'pg_crypt' LANGUAGE c IMMUTABLE STRICT COST 1;
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;AA6C5D,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;;;;;;;;;;;;;;;;;;;;UA4MA"}
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 Promise.all(changesData.map(async (el) => {
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,QAqKlE"}
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.includes(el) || JSON.stringify(req.body || {}).includes(el));
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,gBA6GA"}
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 sql = `with c(id,text) as (select * from (${original.replace("{{parent}}", parent)})q limit ${limit}) select * from c`;
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?.replace(`limit ${limit}`, "limit 0"));
42
- const dataOrigin1 = await pg1.query(`${original.replace("{{parent}}", parent)} limit 0`);
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 (${original.replace("{{parent}}", parent)})q`)
47
- .then((el) => el?.rows?.[0].count));
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;AACpB,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
+ {"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,gBAgbpB"}
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?.key && id
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,gBAsH3D"}
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=$2" : "1=1"}
85
- and resized is null ${limit ? `limit ${limit}` : ""}`;
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,QA8BtC;AAED,eAAe,MAAM,CAAC"}
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.get("/file/resize", {
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
- }, resize);
31
+ handler: resize,
32
+ });
30
33
  }
31
- app.get("/api/resize-all", { config: { tags, role: "admin" }, schema: resizeSchema }, resizeAll);
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.get(`/api/export`, publicParams, exportTable);
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
- type: string;
3
- properties: {
4
- querystring: {
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWjB,CAAC;;AAEF,wBAAoB;AAEpB,OAAO,EAAE,YAAY,EAAE,CAAC"}
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
- type: 'object',
3
- properties: {
4
- querystring: {
5
- filepath: { type: 'string' },
6
- quality: { type: 'number', exclusiveMinimum: 0, maximum: 100 },
7
- size: { type: 'string', pattern: '^((\\d{1,4})x(\\d{1,4})|(\\d{1,4})x|x(\\d{1,4}))$' },
8
- w: { type: 'number', minimum: 1, maximum: 2048 },
9
- h: { type: 'number', minimum: 1, maximum: 2048 },
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":"AAoIA,wBAA8B,MAAM,CAAC,EACnC,EAAqB,EACrB,KAAU,GACX,EAAE,GAAG;;;;;;GAmCL"}
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
- // Math.max(query.offset - res.rows.length,0)
25
- const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : "";
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 '%${query.key}%'`)
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} ${offset} limit ${limit}`;
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((el) => el.rows || []);
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
- .then((el) => +(el?.rows[0]?.count || 0))
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((el) => +(el?.rows[0]?.count || 0))
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 || "16");
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 = "" } = query;
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
- }, reply1?: FastifyReply, called?: any): Promise<any>;
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,MAAM,CAAC,EAAE,YAAY,EACrB,MAAM,CAAC,EAAE,GAAG,gBAq3Bb"}
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, }, reply1, called) {
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
- const offset = query?.page && query?.page > 0 && !objectId
284
- ? ` offset ${(query?.page - 1) * limit}`
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 = loadTable?.meta?.search && query?.search
308
+ const search = isSearchable
290
309
  ? `(${loadTable?.meta?.search
291
310
  ?.split(",")
292
- ?.map((el) => `${el} ilike '%${query?.search
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('${query?.polyline}')),${meta.bbox})`
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}" = $1` : null,
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
- .filter(Boolean)
335
- .filter((el) => checkQuery(el));
336
- const q = `select ${pk ? `"${pk}" as id,` : ""}
337
- ${objectId || query?.key
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
- from (select * ${sql
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
- ${objectId ? cardSqlTable : ""}
353
- where ${where.join(" and ") || "true"}
354
- ${order} ${offset} limit ${limit}`.replace(/{{uid}}/g, uid);
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 { rows = [] } = await pg
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
- search,
436
+ search1,
401
437
  bbox,
402
- queryPolyline,
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
- count(*)::int as total,
420
- count(*) FILTER(WHERE ${filterWhere.join(" and ") || "true"})::int as filtered
421
- ${aggregates.length
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
- from (select * ${sql
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
- where ${[loadTable?.query, tokenData?.query, accessQuery, contextQuery]
464
+ where ${[loadTable?.query, tokenData?.query, accessQuery, contextQuery]
431
465
  .filter(Boolean)
432
- .filter((el) => checkQuery(el))
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 }, data);
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
- pattern: string;
7
+ minimum: number;
8
8
  };
9
9
  page: {
10
10
  type: string;
11
- pattern: string;
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
- pattern: string;
59
+ minimum: number;
61
60
  };
62
61
  page: {
63
62
  type: string;
64
- pattern: string;
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
- pattern: string;
107
+ minimum: number;
110
108
  };
111
109
  limit: {
112
110
  type: string;
113
- pattern: string;
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,GAC1H,CAAC"}
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: 'object',
2
+ type: "object",
3
3
  properties: {
4
4
  querystring: {
5
- limit: { type: 'string', pattern: '^(\\d+)$' },
6
- page: { type: 'string', pattern: '^(\\d+)$' },
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: '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|@{}~_`]+)$' },
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: 'string', pattern: '^(\\d)$' },
16
+ sql: { type: "number" },
17
17
  },
18
18
  params: {
19
- id: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
20
- table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
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: 'object',
25
+ type: "object",
26
26
  properties: {
27
27
  querystring: {
28
- limit: { type: 'string', pattern: '^(\\d+)$' },
29
- page: { type: 'string', pattern: '^(\\d+)$' },
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: 'string', pattern: '^([\\d\\w_.-]+)$' },
33
- desc: { type: 'string', pattern: '^(\\d+)$' },
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: 'string', pattern: '^([\\d\\s,.-]+)$' },
36
+ bbox: { type: "string", pattern: "^([\\d\\s,.-]+)$" },
37
37
  // polyline: { type: 'string', pattern: '^([\\d\\w\\|@\\/\\{\\}~_`]+)$' },
38
- key: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$' },
39
- uid: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
40
- sql: { type: 'string', pattern: '^(\\d)$' },
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: 'string', pattern: '^([\\d\\w]+)$' },
44
- table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
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: 'object',
49
+ type: "object",
50
50
  properties: {
51
51
  querystring: {
52
- page: { type: 'string', pattern: '^(\\d+)$' },
53
- limit: { type: 'string', pattern: '^(\\d+)$' },
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)$' },
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: 'object',
63
+ type: "object",
64
64
  properties: {
65
65
  querystring: {
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_.-]+)$' },
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: 'string', pattern: '([\\d\\w]+)$' },
72
- sql: { type: 'string', pattern: '^(\\d)$' },
73
- count: { type: 'string', pattern: '^(\\d)$' },
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: 'object',
81
+ type: "object",
82
82
  properties: {
83
83
  params: {
84
- name: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
85
- id: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
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: 'object',
90
+ type: "object",
91
91
  properties: {
92
92
  params: {
93
- table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
93
+ table: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
94
94
  },
95
95
  },
96
96
  };
97
97
  const cardTabDataSchema = {
98
- type: 'object',
98
+ type: "object",
99
99
  properties: {
100
100
  querystring: {
101
- sql: { type: 'string', pattern: '^(\\d)$' },
101
+ sql: { type: "string", pattern: "^(\\d)$" },
102
102
  },
103
103
  params: {
104
- token: { type: 'string', pattern: '^([\\d\\w]+)$' },
104
+ token: { type: "string", pattern: "^([\\d\\w]+)$" },
105
105
  },
106
106
  },
107
107
  };
108
108
  const tableDataIdSchema = {
109
- type: 'object',
109
+ type: "object",
110
110
  properties: {
111
111
  params: {
112
- id: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
113
- name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
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,QAMpD"}
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.get("/template/:type/:name", { config: { tags, policy }, schema: getTemplateSchema }, getTemplateApi);
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,7 +1,7 @@
1
1
  declare const getTemplateSchema: {
2
- type: string;
3
- properties: {
4
- params: {
2
+ params: {
3
+ type: string;
4
+ properties: {
5
5
  name: {
6
6
  type: string;
7
7
  pattern: string;
@@ -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;AACpB,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
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
- type: 'object',
3
- properties: {
4
- params: {
5
- name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
2
+ params: {
3
+ type: "object",
4
+ properties: {
5
+ name: { type: "string", pattern: "^([\\d\\w._-]+)$" },
6
6
  // type: { type: 'string' },
7
7
  },
8
8
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [