@opengis/fastify-table 1.0.10 → 1.0.11

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.
@@ -1,5 +1,5 @@
1
1
  import dataInsert from '../funcs/dataInsert.js';
2
- import getIdByToken from '../funcs/getIdByToken.js';
2
+ import getToken from '../funcs/getToken.js';
3
3
  import checkXSS from './utils/checkXSS.js';
4
4
  import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
5
 
@@ -8,7 +8,7 @@ export default async function insert(req) {
8
8
  if (!table) return { status: 404, message: 'table is required' };
9
9
 
10
10
  const { funcs, session, params } = req;
11
- const tokenDataString = await getIdByToken({
11
+ const tokenDataString = await getToken({
12
12
  funcs, session, token: params.table, mode: 'a', json: 0,
13
13
  });
14
14
 
@@ -1,5 +1,5 @@
1
1
  import dataUpdate from '../funcs/dataUpdate.js';
2
- import getIdByToken from '../funcs/getIdByToken.js';
2
+ import getToken from '../funcs/getToken.js';
3
3
  import checkXSS from './utils/checkXSS.js';
4
4
  import getTemplate from '../../table/controllers/utils/getTemplate.js';
5
5
 
@@ -9,7 +9,7 @@ export default async function update(req) {
9
9
  if (!id) return { message: 'id is required', status: 404 };
10
10
 
11
11
  const { funcs, session, params } = req;
12
- const tokenDataString = await getIdByToken({
12
+ const tokenDataString = await getToken({
13
13
  funcs, session, token: params.table, mode: 'w', json: 0,
14
14
  });
15
15
 
@@ -7,7 +7,7 @@ export default async function dataDelete({
7
7
  }) {
8
8
  const pg = getPG({ name: 'client' });
9
9
  const { pk } = await getMeta(table);
10
- if (!pg.tlist.includes(table)) return 'table not exist';
10
+ if (!pg.tlist?.includes(table)) return 'table not exist';
11
11
  const delQuery = `delete from ${table} WHERE ${pk} = $1 returning *`;
12
12
  // console.log(updateDataset);
13
13
  const res = await pg.one(delQuery, [id]) || {};
@@ -8,13 +8,13 @@ export default async function dataUpdate({
8
8
  const pg = getPG({ name: 'client' });
9
9
  const { columns, pk } = await getMeta(table);
10
10
 
11
- const names = columns.map((el) => el.name);
11
+ const names = columns?.map((el) => el.name);
12
12
  const filterData = Object.keys(data)
13
- .filter((el) => data[el] && names.includes(el)).map((el) => [el, data[el]]);
13
+ .filter((el) => data[el] && names?.includes(el)).map((el) => [el, data[el]]);
14
14
 
15
15
  const updateQuery = `UPDATE ${table} SET ${filterData?.map((key, i) => `"${key[0]}"=$${i + 2}`).join(',')}
16
16
  WHERE ${pk} = $1 returning *`;
17
17
  // console.log(updateDataset);
18
- const res = await pg.one(updateQuery, [id, ...filterData.map((el) => (typeof el[1] === 'object' ? JSON.stringify(el[1]) : el[1]))]) || {};
18
+ const res = await pg.query(updateQuery, [id, ...filterData.map((el) => (typeof el[1] === 'object' ? JSON.stringify(el[1]) : el[1]))]).then(el => el?.rows?.[0]) || {};
19
19
  return res;
20
20
  }
@@ -1,4 +1,5 @@
1
1
  import getRedis from '../../redis/funcs/getRedis.js';
2
+ import config from '../../config.js';
2
3
 
3
4
  function sprintf(str, ...args) {
4
5
  return str.replace(/%s/g, () => args.shift());
@@ -12,17 +13,14 @@ const keys = {
12
13
  };
13
14
 
14
15
  async function getIdByToken({
15
- funcs, session, token, mode = 'r', json,
16
+ uid, token, mode = 'r', json,
16
17
  }) {
17
18
  if (mode === 'r') return token;
18
19
 
19
- const { config } = funcs;
20
- const { uid } = session?.passport?.user || (config.local ? { uid: '1' } : {});
20
+ const rclient = getRedis({ db: 0 });
21
21
 
22
- const rclient2 = getRedis({ db: 2, funcs });
23
-
24
- const key = sprintf(keys[mode], config?.pg?.database, uid);
25
- const id = await rclient2.hget(key, token);
22
+ const key = sprintf(keys[mode], config?.pg?.database, uid?.toString());
23
+ const id = await rclient.hget(key, token);
26
24
  return json && id[0] === '{' ? JSON.parse(id) : id;
27
25
  }
28
26
 
@@ -1,5 +1,6 @@
1
1
  import { createHash, randomUUID } from 'crypto';
2
2
 
3
+ import config from '../../config.js';
3
4
  import getRedis from '../../redis/funcs/getRedis.js';
4
5
 
5
6
  const generateCodes = (ids, userToken) => {
@@ -14,14 +15,11 @@ const generateCodes = (ids, userToken) => {
14
15
  return { codes, obj };
15
16
  };
16
17
 
17
- function setTokenById({
18
- funcs, ids: idsOrigin, mode = 'r', session, referer, array,
18
+ function setToken({
19
+ ids: idsOrigin, mode = 'r', uid, referer, array,
19
20
  }) {
20
- const { config } = funcs;
21
- const { uid } = session?.passport?.user || (config.local ? { uid: '1' } : {});
22
-
23
- const rclient2 = getRedis({ db: 2, funcs });
24
- const rclient5 = getRedis({ db: 5, funcs });
21
+ const rclient2 = getRedis({ db: 0 });
22
+ // const rclient5 = getRedis({ db: 0, funcs });
25
23
 
26
24
  if (!uid) return { user: 'empty' };
27
25
  if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
@@ -41,15 +39,15 @@ function setTokenById({
41
39
  }[mode]}:${uid}`, codes);
42
40
 
43
41
  // log token for debug. add extra data - uid, mode, date
44
- const dt = new Date().toISOString();
45
- const codesLog = Object.keys(codes).reduce((acc, key) => {
42
+ /* const dt = new Date().toISOString();
43
+ const codesLog = Object.keys(codes).reduce((acc, key) => {
46
44
  acc[key] = `{"referer": "${referer}" ,"uid":"${uid}","mode":"${mode}","date":"${dt}",${codes[key].substr(1)}`;
47
45
  return acc;
48
46
  }, {});
49
- rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800
47
+ rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800 */
50
48
 
51
49
  // TODO дополнительно писать в hset token -> uid
52
50
  return array ? Object.values(obj) : obj;
53
51
  }
54
52
 
55
- export default setTokenById;
53
+ export default setToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "main": "index.js",
@@ -10,7 +10,7 @@ export default async function getMeta(opt) {
10
10
 
11
11
  if (data[table]) return data[table];
12
12
 
13
- if (!pg.tlist.includes(table)) {
13
+ if (!pg.tlist?.includes(table)) {
14
14
  return { error: `${table} - not found`, status: 400 };
15
15
  }
16
16
 
package/pg/funcs/getPG.js CHANGED
@@ -19,6 +19,9 @@ function getPG({
19
19
  };
20
20
 
21
21
  pgClients[name] = new pg.Pool(dbConfig);
22
+ pgClients[name].init = async () => {
23
+ await init(pgClients[name]);
24
+ };
22
25
  init(pgClients[name]);
23
26
  return pgClients[name];
24
27
  }
package/pg/funcs/init.js CHANGED
@@ -21,7 +21,7 @@ async function init(client) {
21
21
  }
22
22
 
23
23
  async function queryCache(query) {
24
- const rclient = getRedis({ db: 0 })
24
+ const rclient = getRedis({ db: 0 });
25
25
  const hash = crypto.createHash('sha1').update(query).digest('base64');
26
26
  const keyCache = `pg:${hash}`;
27
27
  const cache = await rclient.get(keyCache);
package/pg/pgClients.js CHANGED
@@ -11,7 +11,10 @@ if (config.pg) {
11
11
  user: config.pg?.user || 'postgres',
12
12
  password: config.pg?.password || 'postgres',
13
13
  });
14
- await init(client);
14
+ client.init = async () => {
15
+ await init(client);
16
+ };
17
+ client.init();
15
18
  pgClients.client = client;
16
19
  }
17
20
  export default pgClients;
@@ -2,8 +2,7 @@ import Redis from 'ioredis';
2
2
  import config from '../../config.js';
3
3
  import redisClients from './redisClients.js';
4
4
 
5
- function getRedis({ db, funcs }) {
6
- if (funcs?.config) Object.assign(config, { ...funcs.config }); // unit test
5
+ function getRedis({ db }) {
7
6
  if (!config.redis) return null;
8
7
  if (redisClients[db]) return redisClients[db];
9
8
 
@@ -32,17 +32,17 @@ export default async function data(req) {
32
32
 
33
33
  const limit = Math.min(maxLimit, +(query.limit || 10));
34
34
 
35
- const offset = query.page ? ` offset ${(query.page - 1) * limit}` : '';
35
+ const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
36
36
  // id, query, filter
37
- const orderColumn = query.order || loadTable.order;
37
+ const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
38
38
 
39
- const order = cols.includes(orderColumn) ? `order by ${orderColumn} ${query.desc ? 'desc' : ''}` : '';
39
+ const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
40
40
  const state = loadTable.filterState && query.state ? loadTable.filterState[query.state]?.sql : null;
41
41
  const custom = loadTable.filterCustom && query.custom ? loadTable.filterCustom[query.custom]?.sql : null;
42
42
  const search = loadTable.meta?.search && query.search ? `(${loadTable.meta?.search.split(',').map(el => `${el} ilike '%${query.search}%'`).join(' or ')})` : null;
43
43
 
44
44
  const where = [(params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, state, custom, search].filter((el) => el);
45
- const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'} ${offset} ${order} limit ${limit}`;
45
+ const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
46
46
 
47
47
  if (query.sql === '1') { return q; }
48
48
 
@@ -52,6 +52,6 @@ export default async function data(req) {
52
52
 
53
53
  await metaFormat({ rows, table: params.table });
54
54
  return {
55
- time: Date.now() - time, total, pk, form, rows, meta, columns, filters,
55
+ time: Date.now() - time, total, count: rows.length, pk, form, rows, meta, columns, filters,
56
56
  };
57
57
  }
@@ -0,0 +1,20 @@
1
+ import getSelect from '../../controllers/utils/getSelect.js';
2
+ import pg from '../../../pg/pgClients.js';
3
+ import redis from '../../../redis/client.js';
4
+
5
+ export default async function metaFormat({ name, values }) {
6
+ const cls = await getSelect(name);
7
+ if (!cls?.arr && !cls?.sql) return null;
8
+ const key = `select:${name}`;
9
+ const cache = !cls.arr ? (await redis.hmget(key, values)).reduce((p, el, i) => ({ ...p, [values[i]]: el }), {}) : {};
10
+
11
+ const data = cls.arr || (values.filter(el => !cache[el]).length
12
+ ? await pg.client.query(`with c(id,text) as (${cls.sql}) select * from c where id = any('{${values.filter(el => !cache[el])}}')`).then(el => el.rows)
13
+ : []);
14
+
15
+ const clsAr = { ...cache, ...data.reduce((p, el) => ({ ...p, [el.id.toString()]: el.text }), {}) };
16
+ if (!cls.arr && data.length) {
17
+ redis.hmset(key, clsAr);
18
+ }
19
+ return clsAr;
20
+ }
@@ -1,6 +1,5 @@
1
1
  import getTemplate from '../../controllers/utils/getTemplate.js';
2
- import getSelect from '../../controllers/utils/getSelect.js';
3
- import pg from '../../../pg/pgClients.js';
2
+ import getSelectVal from './getSelectVal.js';
4
3
 
5
4
  export default async function metaFormat({ rows, table }) {
6
5
  const loadTable = await getTemplate('table', table);
@@ -9,14 +8,11 @@ export default async function metaFormat({ rows, table }) {
9
8
  // cls & select format
10
9
 
11
10
  await Promise.all(selectCols?.map(async (attr) => {
12
- const val = [...new Set(rows?.map((el) => el[attr.name]).flat())];
13
- if (!val.filter((el) => el).length) return null;
14
- const cls = await getSelect(attr.data);
15
- if (!cls?.arr && !cls?.sql) return null;
11
+ const val = [...new Set(rows?.map((el) => el[attr.name]).flat())].filter((el) => el);
12
+ if (!val.length) return null;
16
13
 
17
- const data = cls.arr || await pg.client.query(`with c(id,text) as (${cls.sql}) select * from c where id = any('{${val}}')`).then(el => el.rows);
18
-
19
- const clsAr = data.reduce((p, el) => ({ ...p, [el.id.toString()]: el.text }), {});
14
+ const clsAr = await getSelectVal({ name: attr.data, values: val });
15
+ if (!clsAr) return null;
20
16
  rows.forEach(el => {
21
17
  Object.assign(el, { [`${attr.name}_text`]: clsAr[el[attr.name]] || el[attr.name] });
22
18
  });
package/table/index.js CHANGED
@@ -4,12 +4,20 @@ import filter from './controllers/filter.js';
4
4
  import form from './controllers/form.js';
5
5
  import metaFormat from './funcs/metaFormat/index.js';
6
6
 
7
+ const tableSchema = {
8
+ querystring: {
9
+ page: { type: 'number' },
10
+ order: { type: 'string' },
11
+ filter: { type: 'string' },
12
+ },
13
+ };
14
+
7
15
  async function plugin(fastify, config = {}) {
8
16
  const prefix = config.prefix || '/api';
9
17
  fastify.decorate('metaFormat', metaFormat);
10
18
 
11
19
  fastify.get(`${prefix}/suggest/:data`, {}, suggest);
12
- fastify.get(`${prefix}/data/:table/:id?`, {}, data); // vs.crm.data.api с node
20
+ fastify.get(`${prefix}/data/:table/:id?`, { schema: tableSchema }, data); // vs.crm.data.api с node
13
21
  fastify.get(`${prefix}/filter/:table`, {}, filter);
14
22
  fastify.get(`${prefix}/form/:form`, {}, form);
15
23
  }
@@ -3,7 +3,7 @@ import assert from 'node:assert';
3
3
 
4
4
  import build from '../../helper.js';
5
5
 
6
- import setTokenById from '../../crud/funcs/setTokenById.js';
6
+ import setToken from '../../crud/funcs/setToken.js';
7
7
  import config from '../config.js';
8
8
 
9
9
  test('api crud xss', async (t) => {
@@ -17,19 +17,17 @@ test('api crud xss', async (t) => {
17
17
  let editTokens;
18
18
 
19
19
  // before
20
- t.test('setTokenById', async () => {
21
- addTokens = setTokenById({
22
- funcs: { config },
20
+ t.test('setToken', async () => {
21
+ addTokens = setToken({
23
22
  ids: [JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' })],
24
23
  mode: 'a',
25
- session,
24
+ uid: 1,
26
25
  array: 1,
27
26
  });
28
- editTokens = setTokenById({
29
- funcs: { config },
27
+ editTokens = setToken({
30
28
  ids: [JSON.stringify({ id: '5400000', table: 'gis.dataset', form: 'test.dataset.form' })],
31
29
  mode: 'w',
32
- session,
30
+ uid: 1,
33
31
  array: 1,
34
32
  });
35
33
  assert.ok(addTokens.length === 1 && editTokens.length === 1, 'invalid token');
@@ -1,6 +1,6 @@
1
1
  import { test } from 'node:test';
2
2
  import assert from 'node:assert';
3
-
3
+ import config from '../config.js';
4
4
  import pgClients from '../../pg/pgClients.js';
5
5
  import rclient from '../../redis/client.js';
6
6
 
@@ -12,11 +12,11 @@ import isFileExists from '../../crud/funcs/isFileExists.js';
12
12
  import getOpt from '../../crud/funcs/getOpt.js';
13
13
  import setOpt from '../../crud/funcs/setOpt.js';
14
14
 
15
- import getIdByToken from '../../crud/funcs/getIdByToken.js';
16
- import setTokenById from '../../crud/funcs/setTokenById.js';
17
- import config from '../config.js';
15
+ import getToken from '../../crud/funcs/getToken.js';
16
+ import setToken from '../../crud/funcs/setToken.js';
18
17
 
19
18
  test('funcs crud', async (t) => {
19
+ await pgClients.client.init();
20
20
  await t.test('getOpt/setOpt', async () => {
21
21
  const opt = await setOpt({ table: 'gis.dataset' });
22
22
  const data = await getOpt(opt);
@@ -49,20 +49,19 @@ test('funcs crud', async (t) => {
49
49
  const session = { passport: { user: { uid: '1' } } };
50
50
  const tokenData = JSON.stringify({ add: 'gis.dataset', form: 'test.dataset.form' });
51
51
 
52
- await t.test('setTokenById', async () => {
53
- tokens = setTokenById({
52
+ await t.test('setToken', async () => {
53
+ tokens = setToken({
54
54
  funcs: { config },
55
55
  ids: [tokenData],
56
56
  mode: 'a',
57
- session,
57
+ uid: 1,
58
58
  array: 1,
59
59
  });
60
60
  assert.equal(tokens.length, 1);
61
61
  });
62
- await t.test('getIdByToken', async () => {
63
- const data = await getIdByToken({
64
- funcs: { config },
65
- session,
62
+ await t.test('getToken', async () => {
63
+ const data = await getToken({
64
+ uid: 1,
66
65
  token: tokens[0],
67
66
  mode: 'a',
68
67
  });
@@ -7,19 +7,20 @@ import getMeta from '../../pg/funcs/getMeta.js';
7
7
  import autoIndex from '../../pg/funcs/autoIndex.js';
8
8
  import pgClients from '../../pg/pgClients.js';
9
9
  import rclient from '../../redis/client.js';
10
- import getPG from '../../pg/funcs/getPG.js'
10
+ // import pgClients from '../../pg/funcs/pgClients.js';
11
11
 
12
12
  test('funcs pg', async (t) => {
13
+ await pgClients.client.init();
13
14
  await t.test('getMeta', async () => {
14
15
  const { columns } = await getMeta({ table: 'gis.dataset' });
15
16
  // console.log(columns)
16
17
  assert.ok(columns);
17
18
  });
18
19
 
19
- await t.test('getPG', async (t) => {
20
+ /* await t.test('getPG', async (t) => {
20
21
  const data = await getPG({});
21
22
  assert.ok(data);
22
- });
23
+ }); */
23
24
 
24
25
  await t.test('autoIndex', async () => {
25
26
  await autoIndex({ table: 'gis.dataset', columns: ['service_type'] });
@@ -27,6 +28,7 @@ test('funcs pg', async (t) => {
27
28
  });
28
29
  t.after(() => {
29
30
  pgClients.client.end();
31
+
30
32
  rclient.quit();
31
33
  });
32
34
  });
@@ -1,48 +0,0 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert';
3
- import '../config.js';
4
- import pgClients from '../../pg/pgClients.js';
5
- import rclient from '../../redis/client.js';
6
- import getFilterSQL from '../../table/funcs/getFilterSQL/index.js';
7
- import getTableSql from '../../table/funcs/getFilterSQL/index.js';
8
- import getCustomQuery from '../../table/funcs/getFilterSQL/index.js';
9
- import getFilterQuery from '../../table/funcs/getFilterSQL/index.js';
10
- import formatValue from '../../table/funcs/getFilterSQL/index.js';
11
- import getOptimizedQuery from '../../table/funcs/getFilterSQL/index.js';
12
-
13
- test('fucns table', async (t) => {
14
- await t.test('getMeta', async () => {
15
- const data = await getFilterSQL({ table: 'gis.dataset', filter: 'service_type=1' });
16
- // console.log(data);
17
- assert.ok(data.q);
18
- });
19
-
20
- await t.test('formatValue', async (t) => {
21
- const data = await formatValue( {table: 'gis.dataset'} );
22
- assert.ok(data);
23
- });
24
-
25
- await t.test('getCustomQuery', async (t) => {
26
- const data = await getCustomQuery( {table: 'gis.dataset'} );
27
- assert.ok(data);
28
- });
29
-
30
- await t.test('getFilterQuery', async (t) => {
31
- const data = await getFilterQuery( {table: 'gis.dataset'} );
32
- assert.ok(data);
33
- });
34
-
35
- await t.test('getOptimizedQuery', async (t) => {
36
- const data = await getOptimizedQuery( {table: 'gis.dataset'} );
37
- assert.ok(data);
38
- });
39
-
40
- await t.test('getTableSql', async (t) => {
41
- const data = await getTableSql( {table: 'gis.dataset'} );
42
- assert.ok(data);
43
- });
44
- t.after(() => {
45
- pgClients.client.end();
46
- rclient.quit();
47
- });
48
- });