@opengis/bi 1.1.2 → 1.2.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 (32) hide show
  1. package/dist/bi.js +11 -2
  2. package/dist/bi.umd.cjs +72 -720
  3. package/dist/import-file-D06AZEtP.js +3493 -0
  4. package/dist/style.css +1 -7
  5. package/dist/{vs-funnel-bar-mWZ8lvEq.js → vs-funnel-bar-C8m-602x.js} +11 -11
  6. package/dist/vs-list-BJ0NjSm5.js +525 -0
  7. package/dist/vs-map-PLlJqaaW.js +294 -0
  8. package/dist/vs-map-cluster-9tV6eiDA.js +356 -0
  9. package/dist/{vs-number-CRUhHKym.js → vs-number-B2V_BPer.js} +3 -3
  10. package/dist/{vs-table-OddIdr1s.js → vs-table-WGE9jyDq.js} +6 -6
  11. package/dist/vs-text-DkLKRC7F.js +1528 -0
  12. package/package.json +77 -84
  13. package/plugin.js +13 -13
  14. package/server/plugins/vite.js +69 -69
  15. package/server/routes/dashboard/controllers/utils/yaml.js +11 -11
  16. package/server/routes/data/controllers/data.js +7 -6
  17. package/server/routes/data/controllers/util/chartSQL.js +2 -2
  18. package/server/routes/map/controllers/cluster.js +125 -125
  19. package/server/routes/map/controllers/clusterVtile.js +166 -166
  20. package/server/routes/map/controllers/geojson.js +127 -127
  21. package/server/routes/map/controllers/map.js +69 -69
  22. package/server/routes/map/controllers/utils/downloadClusterData.js +44 -44
  23. package/server/routes/map/controllers/vtile.js +183 -183
  24. package/server/utils/getWidget.js +3 -3
  25. package/utils.js +12 -12
  26. package/config.js +0 -12
  27. package/dist/import-file-XFI3CaVb.js +0 -63458
  28. package/dist/vs-donut-al85JwBt.js +0 -148
  29. package/dist/vs-list-1QDnN3pH.js +0 -18510
  30. package/dist/vs-map-CwR6ZYur.js +0 -285
  31. package/dist/vs-map-cluster-YdXTBIVf.js +0 -314
  32. package/dist/vs-text-CQ9vn0qO.js +0 -40
@@ -1,183 +1,183 @@
1
- import Sphericalmercator from '@mapbox/sphericalmercator';
2
-
3
- import path from 'path';
4
- import { createHash } from 'crypto';
5
- import { writeFile, mkdir } from 'fs/promises';
6
- import { existsSync, /* readdirSync, */ readFileSync } from 'fs';
7
- import { getWidget } from '../../../../utils.js';
8
-
9
- import { getFolder, getFilterSQL, logger, pgClients } from '@opengis/fastify-table/utils.js';
10
-
11
- import normalizeData from '../../data/controllers/util/normalizeData.js';
12
-
13
- const mercator = new Sphericalmercator({ size: 256 });
14
-
15
- const types = {
16
- point: 'ST_Point' /* ,ST_MultiPoint */,
17
- polygon: 'ST_Polygon,ST_MultiPolygon',
18
- };
19
-
20
- const area = {
21
- 1: 1000000,
22
- 2: 100000,
23
- 3: 100000,
24
- 4: 100000,
25
- 5: 100000,
26
- 6: 100000,
27
- 7: 100000,
28
- 8: 100000,
29
- 9: 100000,
30
- 10: 50000,
31
- 11: 40000,
32
- 12: 20000,
33
- 13: 20000,
34
- };
35
-
36
- export default async function vtile(req, reply) {
37
- const { params = {}, query = {} } = req;
38
-
39
- const {
40
- filter,
41
- widget,
42
- dashboard,
43
- sql,
44
- cluster,
45
- type,
46
- nocache,
47
- geom = 'geom',
48
- pointZoom = 0,
49
- } = query;
50
-
51
- if (!widget) {
52
- return { message: 'not enough params: widget', status: 400 };
53
- }
54
-
55
- const { y, z } = params;
56
- const x = params.x?.split('.')[0] - 0;
57
-
58
- if (!x || !y || !z) {
59
- return { message: 'not enough params: xyz', status: 400 };
60
- }
61
-
62
- const { pg = req.pg || pgClients.client, data } = await getWidget({ pg: req.pg, widget, dashboard });
63
-
64
- const headers = {
65
- 'Content-Type': 'application/x-protobuf',
66
- 'Cache-Control': nocache || sql ? 'no-cache' : 'public, max-age=86400',
67
- };
68
-
69
- const hash = [pointZoom, filter].filter((el) => el).join();
70
-
71
- const root = getFolder(req);
72
- const file = path.join(
73
- root,
74
- `/map/vtile/${widget}/${hash ? `${createHash('sha1').update(hash).digest('base64')}/` : ''}${z}/${x}/${y}.mvt`
75
- );
76
-
77
- try {
78
- const pkey = pg.pk?.[data?.table];
79
- if (!pkey) {
80
- return {
81
- message: `invalid ${widget ? 'widget' : 'dashboard'}: table pk not found (${data?.table})`,
82
- status: 400,
83
- };
84
- }
85
-
86
- // data param
87
- const {
88
- table,
89
- where = '1=1',
90
- xName = {},
91
- metric,
92
- } = normalizeData(data, query);
93
-
94
- // get sql
95
- const columns = data.columns?.map((el) => el.name || el)?.join(',') || '1';
96
- const filterQ = filter
97
- ? await getFilterSQL({ pg, table, filter })
98
- : undefined;
99
- const q = `select "${pkey}",
100
- ${data?.color ? `"${data?.color}"` : '0'} as x,
101
- ${data.metrics?.[0] ? `"${data.metrics[0]}"::float` : '0'} as metric,
102
- ${columns},
103
- ${geom} as geom
104
- from ${filterQ ? `(${filterQ})` : table} q where ${where}`;
105
-
106
- if (sql === '1') return q;
107
-
108
- const koef =
109
- {
110
- 10: 0.1,
111
- 11: 0.05,
112
- 12: 0.005,
113
- 13: 0.0002,
114
- 14: 0.00005,
115
- }[z] || 0.000001;
116
-
117
- const geomCol =
118
- parseInt(z, 10) < parseInt(pointZoom, 10) || true
119
- ? `ST_Centroid(${geom})`
120
- : geom;
121
-
122
- const bbox = mercator.bbox(+y, +x, +z, false /* , '900913' */);
123
- const bbox2d = `'BOX(${bbox[0]} ${bbox[1]},${bbox[2]} ${bbox[3]})'::box2d`;
124
-
125
- const areaZoom =
126
- area[z] && false
127
- ? ` and (st_area(st_transform(${geom},3857)))>'${area[z]}'`
128
- : '';
129
-
130
- const q1 =
131
- cluster > z
132
- ? `SELECT ST_AsMVT(q, 'bi', 4096, 'geom','row') as tile
133
- FROM (
134
- SELECT floor(random() * 100000 + 1)::int + row_number() over() as row, count(*) as point_count,
135
- ST_AsMVTGeom(st_transform(st_centroid(ST_Union(geom)),3857),ST_TileEnvelope(${z},${y},${x})::box2d,4096,256,false) as geom
136
- FROM (
137
- SELECT geom, ST_ClusterDBSCAN(geom,${koef},1) OVER () AS cluster
138
- FROM (${q})q where ${geom} && ${bbox2d} ) j
139
- WHERE cluster IS NOT NULL
140
- GROUP BY cluster
141
- ORDER BY 1 DESC
142
- )q`
143
- : `SELECT ST_AsMVT(q, 'bi', 4096, 'geom','row') as tile
144
- FROM (
145
- SELECT
146
- floor(random() * 100000 + 1)::int + row_number() over() as row,
147
-
148
- ${pkey} as id,
149
- x,
150
- metric,
151
- ${columns},
152
- ST_AsMVTGeom(st_transform(${geomCol}, 3857),ST_TileEnvelope(${z},${y},${x})::box2d,4096,256,false) as geom
153
-
154
- FROM (select * from (${q})q where ${geom} && ${bbox2d}
155
-
156
- and ${geom} is not null and st_srid(${geom}) >0
157
-
158
- ${areaZoom}
159
-
160
- ${types[type] ? ` and ST_GeometryType(geom) = any ('{ ${types[type]} }') ` : ''}
161
-
162
- limit 3000)q
163
- ) q`;
164
-
165
- if (sql === '2') return q1;
166
-
167
- const { rows = [] } = await pg.query(q1);
168
-
169
- if (sql === '3') return rows.map((el) => el.tile);
170
-
171
- const buffer = Buffer.concat(rows.map((el) => Buffer.from(el.tile)));
172
-
173
- if (!nocache) {
174
- await mkdir(path.dirname(file), { recursive: true });
175
- await writeFile(file, buffer, 'binary');
176
- }
177
-
178
- return reply.headers(headers).send(buffer);
179
- } catch (err) {
180
- logger.file('bi/vtile', { level: 'ERROR', error: err.toString(), query, params });
181
- return { error: err.toString(), status: 500 };
182
- }
183
- }
1
+ import Sphericalmercator from '@mapbox/sphericalmercator';
2
+
3
+ import path from 'path';
4
+ import { createHash } from 'crypto';
5
+ import { writeFile, mkdir } from 'fs/promises';
6
+ import { existsSync, /* readdirSync, */ readFileSync } from 'fs';
7
+ import { getWidget } from '../../../../utils.js';
8
+
9
+ import { getFolder, getFilterSQL, logger, pgClients } from '@opengis/fastify-table/utils.js';
10
+
11
+ import normalizeData from '../../data/controllers/util/normalizeData.js';
12
+
13
+ const mercator = new Sphericalmercator({ size: 256 });
14
+
15
+ const types = {
16
+ point: 'ST_Point' /* ,ST_MultiPoint */,
17
+ polygon: 'ST_Polygon,ST_MultiPolygon',
18
+ };
19
+
20
+ const area = {
21
+ 1: 1000000,
22
+ 2: 100000,
23
+ 3: 100000,
24
+ 4: 100000,
25
+ 5: 100000,
26
+ 6: 100000,
27
+ 7: 100000,
28
+ 8: 100000,
29
+ 9: 100000,
30
+ 10: 50000,
31
+ 11: 40000,
32
+ 12: 20000,
33
+ 13: 20000,
34
+ };
35
+
36
+ export default async function vtile(req, reply) {
37
+ const { params = {}, query = {} } = req;
38
+
39
+ const {
40
+ filter,
41
+ widget,
42
+ dashboard,
43
+ sql,
44
+ cluster,
45
+ type,
46
+ nocache,
47
+ geom = 'geom',
48
+ pointZoom = 0,
49
+ } = query;
50
+
51
+ if (!widget) {
52
+ return { message: 'not enough params: widget', status: 400 };
53
+ }
54
+
55
+ const { y, z } = params;
56
+ const x = params.x?.split('.')[0] - 0;
57
+
58
+ if (!x || !y || !z) {
59
+ return { message: 'not enough params: xyz', status: 400 };
60
+ }
61
+
62
+ const { pg = req.pg || pgClients.client, data } = await getWidget({ pg: req.pg, widget, dashboard });
63
+
64
+ const headers = {
65
+ 'Content-Type': 'application/x-protobuf',
66
+ 'Cache-Control': nocache || sql ? 'no-cache' : 'public, max-age=86400',
67
+ };
68
+
69
+ const hash = [pointZoom, filter].filter((el) => el).join();
70
+
71
+ const root = getFolder(req);
72
+ const file = path.join(
73
+ root,
74
+ `/map/vtile/${widget}/${hash ? `${createHash('sha1').update(hash).digest('base64')}/` : ''}${z}/${x}/${y}.mvt`
75
+ );
76
+
77
+ try {
78
+ const pkey = pg.pk?.[data?.table];
79
+ if (!pkey) {
80
+ return {
81
+ message: `invalid ${widget ? 'widget' : 'dashboard'}: table pk not found (${data?.table})`,
82
+ status: 400,
83
+ };
84
+ }
85
+
86
+ // data param
87
+ const {
88
+ table,
89
+ where = '1=1',
90
+ xName = {},
91
+ metric,
92
+ } = normalizeData(data, query);
93
+
94
+ // get sql
95
+ const columns = data.columns?.map((el) => el.name || el)?.join(',') || '1';
96
+ const filterQ = filter
97
+ ? await getFilterSQL({ pg, table, filter })
98
+ : undefined;
99
+ const q = `select "${pkey}",
100
+ ${data?.color ? `"${data?.color}"` : '0'} as x,
101
+ ${data.metrics?.[0] ? `"${data.metrics[0]}"::float` : '0'} as metric,
102
+ ${columns},
103
+ ${geom} as geom
104
+ from ${filterQ ? `(${filterQ})` : table} q where ${where}`;
105
+
106
+ if (sql === '1') return q;
107
+
108
+ const koef =
109
+ {
110
+ 10: 0.1,
111
+ 11: 0.05,
112
+ 12: 0.005,
113
+ 13: 0.0002,
114
+ 14: 0.00005,
115
+ }[z] || 0.000001;
116
+
117
+ const geomCol =
118
+ parseInt(z, 10) < parseInt(pointZoom, 10) || true
119
+ ? `ST_Centroid(${geom})`
120
+ : geom;
121
+
122
+ const bbox = mercator.bbox(+y, +x, +z, false /* , '900913' */);
123
+ const bbox2d = `'BOX(${bbox[0]} ${bbox[1]},${bbox[2]} ${bbox[3]})'::box2d`;
124
+
125
+ const areaZoom =
126
+ area[z] && false
127
+ ? ` and (st_area(st_transform(${geom},3857)))>'${area[z]}'`
128
+ : '';
129
+
130
+ const q1 =
131
+ cluster > z
132
+ ? `SELECT ST_AsMVT(q, 'bi', 4096, 'geom','row') as tile
133
+ FROM (
134
+ SELECT floor(random() * 100000 + 1)::int + row_number() over() as row, count(*) as point_count,
135
+ ST_AsMVTGeom(st_transform(st_centroid(ST_Union(geom)),3857),ST_TileEnvelope(${z},${y},${x})::box2d,4096,256,false) as geom
136
+ FROM (
137
+ SELECT geom, ST_ClusterDBSCAN(geom,${koef},1) OVER () AS cluster
138
+ FROM (${q})q where ${geom} && ${bbox2d} ) j
139
+ WHERE cluster IS NOT NULL
140
+ GROUP BY cluster
141
+ ORDER BY 1 DESC
142
+ )q`
143
+ : `SELECT ST_AsMVT(q, 'bi', 4096, 'geom','row') as tile
144
+ FROM (
145
+ SELECT
146
+ floor(random() * 100000 + 1)::int + row_number() over() as row,
147
+
148
+ ${pkey} as id,
149
+ x,
150
+ metric,
151
+ ${columns},
152
+ ST_AsMVTGeom(st_transform(${geomCol}, 3857),ST_TileEnvelope(${z},${y},${x})::box2d,4096,256,false) as geom
153
+
154
+ FROM (select * from (${q})q where ${geom} && ${bbox2d}
155
+
156
+ and ${geom} is not null and st_srid(${geom}) >0
157
+
158
+ ${areaZoom}
159
+
160
+ ${types[type] ? ` and ST_GeometryType(geom) = any ('{ ${types[type]} }') ` : ''}
161
+
162
+ limit 3000)q
163
+ ) q`;
164
+
165
+ if (sql === '2') return q1;
166
+
167
+ const { rows = [] } = await pg.query(q1);
168
+
169
+ if (sql === '3') return rows.map((el) => el.tile);
170
+
171
+ const buffer = Buffer.concat(rows.map((el) => Buffer.from(el.tile)));
172
+
173
+ if (!nocache) {
174
+ await mkdir(path.dirname(file), { recursive: true });
175
+ await writeFile(file, buffer, 'binary');
176
+ }
177
+
178
+ return reply.headers(headers).send(buffer);
179
+ } catch (err) {
180
+ logger.file('bi/vtile', { level: 'ERROR', error: err.toString(), query, params });
181
+ return { error: err.toString(), status: 500 };
182
+ }
183
+ }
@@ -98,14 +98,14 @@ async function getWidget({ pg: pg1 = pgClients.client, dashboard, widget }) {
98
98
  };
99
99
  }
100
100
 
101
- const tableSQL = main?.tableSQL?.map(
101
+ const tableSQL = Array.isArray(main?.tableSQL) ? main?.tableSQL?.map?.(
102
102
  (el, i) => `left join lateral(${el})t${i + 1} on 1=1`
103
- );
103
+ )?.join?.(' ') : main?.tableSQL;
104
104
 
105
105
  const columnList = columns.map(col => col.name);
106
106
 
107
107
  const res = { ...main, pg: widgetDb, sql: widgetData?.sql, limit: widgetData?.limit, tableSQL, data, type, text, controls, style, options, yml };
108
- if (res.x && !columnList.includes(res.x) && !loadTemplate?.table && !tableSQL?.join()?.includes(res.x)) {
108
+ if (res.x && !columnList.includes(res.x) && !loadTemplate?.table && !tableSQL?.includes?.(res.x)) {
109
109
  Object.assign(res, { x: null, error: `column does not exists: ${res.x} at table ${res.table}` });
110
110
  }
111
111
  if (loadTemplate?.table) {
package/utils.js CHANGED
@@ -1,12 +1,12 @@
1
- // This file contains code that we reuse
2
- // between our tests.
3
-
4
- // import getTemplatePath from '@opengis/fastify-table/table/controllers/utils/getTemplatePath.js';
5
- import getWidget from './server/utils/getWidget.js';
6
- import yamlSafe from './server/routes/dashboard/controllers/utils/yaml.js';
7
-
8
- export {
9
- // getTemplatePath,
10
- yamlSafe,
11
- getWidget,
12
- };
1
+ // This file contains code that we reuse
2
+ // between our tests.
3
+
4
+ // import getTemplatePath from '@opengis/fastify-table/table/controllers/utils/getTemplatePath.js';
5
+ import getWidget from './server/utils/getWidget.js';
6
+ import yamlSafe from './server/routes/dashboard/controllers/utils/yaml.js';
7
+
8
+ export {
9
+ // getTemplatePath,
10
+ yamlSafe,
11
+ getWidget,
12
+ };
package/config.js DELETED
@@ -1,12 +0,0 @@
1
- import { existsSync, readFileSync } from 'fs';
2
-
3
- const fileName = ['/data/local/config.json', 'config.json'].find((el) =>
4
- existsSync(el) ? el : null
5
- );
6
- const config = fileName ? JSON.parse(readFileSync(fileName), '{}') : {};
7
-
8
- Object.assign(config, {
9
- allTemplates: config?.allTemplates || {},
10
- });
11
-
12
- export default config;