@opengis/gis 0.2.126 → 0.2.128

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 (24) hide show
  1. package/dist/{CardIcon-BLMtCXLH.js → CardIcon-DgpYeKbG.js} +1 -1
  2. package/dist/{EntityTablePage-C4myYlFG.js → EntityTablePage-DNdVavT4.js} +1 -1
  3. package/dist/{ExtentOutlineLayer.vue_vue_type_script_setup_true_lang-DbJh2Fwh.js → ExtentOutlineLayer.vue_vue_type_script_setup_true_lang-DQnIBCpE.js} +1 -1
  4. package/dist/{HeaderActions.vue_vue_type_script_setup_true_lang-K7A_UX_L.js → HeaderActions.vue_vue_type_script_setup_true_lang-Cg2y4sIa.js} +234 -207
  5. package/dist/{MapSettings-DB00GdG3.js → MapSettings-CHF3VpUu.js} +1 -1
  6. package/dist/{RastersTablePage-BJ8Fx2lR.js → RastersTablePage-Ci3P3r4c.js} +1 -1
  7. package/dist/{cartocss-C9FsDCQE.js → cartocss-BsaIlSRb.js} +5 -5
  8. package/dist/{import-utils-CGjOAbEq.js → import-utils-ElncWVJV.js} +1 -1
  9. package/dist/{index-DWGGabsq.js → index-UGx54M0Q.js} +10 -10
  10. package/dist/index.js +1 -1
  11. package/dist/index.umd.cjs +15 -15
  12. package/dist/{raster-fgKYYXVI.js → raster-BDWEafwx.js} +3 -3
  13. package/dist/{register-C-I3igBi.js → register-BfNUPbey.js} +3 -3
  14. package/dist/{service-dErle1NR.js → service-DsykdHry.js} +5 -5
  15. package/dist/{vs-datatable-BKFXZaVJ.js → vs-datatable-D6g7tjZo.js} +1 -1
  16. package/package.json +1 -1
  17. package/server/plugins/mapnik/map.proto +2 -0
  18. package/server/routes/gis/checkXML.js +0 -1
  19. package/server/routes/mapnik/controllers/mapnikStat.js +1 -2
  20. package/server/routes/mapnik/controllers/pretile.js +145 -0
  21. package/server/routes/mapnik/controllers/rasterInfo.js +0 -1
  22. package/server/routes/mapnik/functions/cartoBounds.js +2 -2
  23. package/server/routes/mapnik/functions/convertBoundToTile.js +27 -0
  24. package/server/routes/mapnik/index.js +13 -0
@@ -1,9 +1,9 @@
1
1
  import { defineComponent as F, resolveDirective as Ce, openBlock as o, createElementBlock as d, createElementVNode as s, Fragment as q, renderList as B, toDisplayString as c, withDirectives as ie, createTextVNode as Re, normalizeClass as W, ref as h, watch as S, computed as g, vModelText as Ee, onMounted as Se, onBeforeUnmount as Ie, unref as je, createCommentVNode as U, createVNode as M, withCtx as ze, createBlock as L, resolveDynamicComponent as Me } from "vue";
2
2
  import { useRouter as Le, useRoute as Ne } from "vue-router";
3
3
  import { TooltipDirective as Ue, notify as D } from "@opengis/core";
4
- import { _ as qe, u as Be, f as Te, M as De, i as Pe, j as re, F as Fe } from "./index-DWGGabsq.js";
5
- import { _ as Ve, a as Qe, b as Ge, c as Ae } from "./HeaderActions.vue_vue_type_script_setup_true_lang-K7A_UX_L.js";
6
- import { _ as Oe } from "./ExtentOutlineLayer.vue_vue_type_script_setup_true_lang-DbJh2Fwh.js";
4
+ import { _ as qe, u as Be, f as Te, M as De, i as Pe, j as re, F as Fe } from "./index-UGx54M0Q.js";
5
+ import { _ as Ve, a as Qe, b as Ge, c as Ae } from "./HeaderActions.vue_vue_type_script_setup_true_lang-Cg2y4sIa.js";
6
+ import { _ as Oe } from "./ExtentOutlineLayer.vue_vue_type_script_setup_true_lang-DQnIBCpE.js";
7
7
  const We = { class: "flex-1 overflow-y-auto p-4 sm:p-6" }, Xe = { class: "space-y-3" }, Ye = { class: "bg-white p-3 rounded-xl border border-gray-200 shadow-sm" }, Ke = { class: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2" }, Ze = { class: "text-xs text-gray-500 mb-1" }, He = {
8
8
  key: 0,
9
9
  class: "text-base text-md font-semibold text-gray-900"
@@ -2,9 +2,9 @@ import { defineComponent as B, mergeModels as j, useModel as S, computed as h, d
2
2
  import { useRoute as Z, useRouter as ee } from "vue-router";
3
3
  import { notify as F } from "@opengis/core";
4
4
  import { _ as te } from "./TableFormHeader.vue_vue_type_script_setup_true_lang-Mci_tseM.js";
5
- import { V as N } from "./vs-datatable-BKFXZaVJ.js";
6
- import { _ as z, n as R, m as E, r as H } from "./import-utils-CGjOAbEq.js";
7
- import { a as ae, b as le, c as se, d as oe, e as ie } from "./index-DWGGabsq.js";
5
+ import { V as N } from "./vs-datatable-D6g7tjZo.js";
6
+ import { _ as z, n as R, m as E, r as H } from "./import-utils-ElncWVJV.js";
7
+ import { a as ae, b as le, c as se, d as oe, e as ie } from "./index-UGx54M0Q.js";
8
8
  import { LucideChevronRight as re } from "lucide-vue-next";
9
9
  import { _ as ne } from "./MapSettingsTabs.vue_vue_type_script_setup_true_lang-CKCK3NqY.js";
10
10
  const ue = { class: "vs-form" }, de = { class: "vs-form__body auto-rows-max container" }, ce = { class: "flex flex-wrap" }, me = { class: "h-fit w-full mb-6 bg-white border border-gray-200 rounded-lg p-6" }, ve = { class: "h-fit w-full flex flex-wrap" }, pe = { class: "w-full" }, fe = /* @__PURE__ */ B({
@@ -1,12 +1,12 @@
1
1
  import { openBlock as C, createElementBlock as M, createElementVNode as v, defineComponent as Z, ref as S, watch as T, createTextVNode as Di, createVNode as j, createBlock as N, createCommentVNode as P, defineAsyncComponent as Ri, unref as ve, withCtx as qe, withDirectives as Be, vModelText as Ye, normalizeClass as he, Fragment as Nn, renderList as Mn, toDisplayString as te, getCurrentInstance as Dn, onBeforeUnmount as Rn, toRef as $i, computed as Se, onMounted as ji, resolveDynamicComponent as Ui } from "vue";
2
2
  import { useRoute as Bi, useRouter as Yi } from "vue-router";
3
3
  import { notify as z } from "@opengis/core";
4
- import { _ as Ne, u as $n, f as Pi, M as Hi, g as Vi, h as qi, i as Ki, j as mn, k as zi, l as Gi, m as Qi, s as hn } from "./index-DWGGabsq.js";
5
- import { _ as Wi, a as Ji, b as Zi, c as Xi } from "./HeaderActions.vue_vue_type_script_setup_true_lang-K7A_UX_L.js";
6
- import { S as el, C as nl } from "./CardIcon-BLMtCXLH.js";
4
+ import { _ as Ne, u as $n, f as Pi, M as Hi, g as Vi, h as qi, i as Ki, j as mn, k as zi, l as Gi, m as Qi, s as hn } from "./index-UGx54M0Q.js";
5
+ import { _ as Wi, a as Ji, b as Zi, c as Xi } from "./HeaderActions.vue_vue_type_script_setup_true_lang-Cg2y4sIa.js";
6
+ import { S as el, C as nl } from "./CardIcon-DgpYeKbG.js";
7
7
  import { _ as jn } from "./MonacoEditor.vue_vue_type_script_setup_true_lang-D3ZPeXMw.js";
8
- import { V as Me } from "./vs-datatable-BKFXZaVJ.js";
9
- import { _ as Je, m as Ze, r as xe } from "./import-utils-CGjOAbEq.js";
8
+ import { V as Me } from "./vs-datatable-D6g7tjZo.js";
9
+ import { _ as Je, m as Ze, r as xe } from "./import-utils-ElncWVJV.js";
10
10
  /*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
11
11
  function Un(e) {
12
12
  return typeof e > "u" || e === null;
@@ -1,7 +1,7 @@
1
1
  import { defineComponent as F, mergeModels as O, defineAsyncComponent as I, useModel as R, ref as y, watch as K, openBlock as o, createElementBlock as s, createElementVNode as e, createVNode as $, unref as x, withCtx as S, createStaticVNode as V, useSlots as P, computed as H, Fragment as b, createTextVNode as U, createCommentVNode as N, renderList as A, normalizeStyle as Q, toDisplayString as M, normalizeClass as z, withModifiers as X, createBlock as Y, resolveDynamicComponent as ee, withDirectives as te, renderSlot as ne } from "vue";
2
2
  import { notify as E } from "@opengis/core";
3
3
  import { Edit as le, Trash as oe } from "lucide-vue-next";
4
- import { _ as u } from "./index-DWGGabsq.js";
4
+ import { _ as u } from "./index-UGx54M0Q.js";
5
5
  const se = { class: "flex items-center justify-center col-span-3 gap-2" }, re = { class: "flex justify-end p-[20px] gap-[10px] border-t w-full" }, ie = /* @__PURE__ */ F({
6
6
  __name: "vs-datatable-controls",
7
7
  props: /* @__PURE__ */ O({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/gis",
3
- "version": "0.2.126",
3
+ "version": "0.2.128",
4
4
  "type": "module",
5
5
  "author": "Softpro",
6
6
  "main": "./dist/index.js",
@@ -31,6 +31,7 @@ message RenderTileRequest {
31
31
  string path = 2;
32
32
  repeated double bbox = 3; // [minx, miny, maxx, maxy]
33
33
  int32 width = 4;
34
+ string ttl = 5; // "5m", "1h", "1d" or "0"
34
35
  string debug = 6;
35
36
  }
36
37
 
@@ -39,6 +40,7 @@ message RenderTileOut {
39
40
  bool cache = 2;
40
41
  string err = 3;
41
42
  string xml_path = 4;
43
+ string tile_path = 5;
42
44
  }
43
45
 
44
46
  message ClearTileRequest {
@@ -45,7 +45,6 @@ export default async function checkXML(req, reply) {
45
45
 
46
46
  const rasterInfo = await GetRasterInfo({
47
47
  path: row.source_path,
48
- ttl: '0',
49
48
  }).catch(err => ({ err }));
50
49
 
51
50
  if (rasterInfo.err) {
@@ -5,7 +5,7 @@ import mapnik from '../../../plugins/mapnik/funcs/mapnik.js';
5
5
  const { GetStat } = mapnik();
6
6
 
7
7
  export default async function mapnikStat({
8
- params, query,
8
+ params,
9
9
  }, reply) {
10
10
  if (!config.mapnik?.server) {
11
11
  return reply.status(400).send({ error: 'mapnik server address needed', code: 400 });
@@ -13,7 +13,6 @@ export default async function mapnikStat({
13
13
 
14
14
  const stat = await GetStat({
15
15
  period: params.period,
16
- ttl: query.nocache ? '0' : undefined,
17
16
  });
18
17
 
19
18
  return reply.status(200).send(stat);
@@ -0,0 +1,145 @@
1
+ import SphericalMercator from '@mapbox/sphericalmercator';
2
+
3
+ import {
4
+ config, logger, eventStream, pgClients,
5
+ } from '@opengis/fastify-table/utils.js';
6
+
7
+ import convertBoundToTile from '../functions/convertBoundToTile.js';
8
+ import mapnik from '../../../plugins/mapnik/funcs/mapnik.js';
9
+ import cartoBounds from '../functions/cartoBounds.js';
10
+
11
+ const { RenderTile } = mapnik();
12
+
13
+ const mercator = new SphericalMercator({ size: 256 });
14
+
15
+ const MAX_LIMIT = 100000;
16
+
17
+ const CONCURRENCY = 5;
18
+
19
+ async function runPool(tasks, limit) {
20
+ return tasks.reduce(async (acc, task) => {
21
+ const pool = await acc;
22
+
23
+ const p = task().finally(() => {
24
+ const i = pool.indexOf(p);
25
+ if (i !== -1) pool.splice(i, 1);
26
+ });
27
+
28
+ pool.push(p);
29
+
30
+ if (pool.length >= limit) {
31
+ await Promise.race(pool);
32
+ }
33
+
34
+ return pool;
35
+ }, Promise.resolve([])).then((pool) => Promise.all(pool));
36
+ }
37
+
38
+ const maxBounds = [23, 44, 40, 53];
39
+
40
+ export default async function pretile({
41
+ pg = pgClients.client, params, query,
42
+ }, reply) {
43
+ const { zoom = 11, max = 15 } = query || {};
44
+
45
+ if (zoom > max) {
46
+ return reply.status(422).send({ error: 'Error: querystring/max must be > querystring/zoom', code: 422 });
47
+ }
48
+
49
+ const data = await pg.query(`select *, geom::box2d as bounds, 'raster' as source_type from gis.rasters where raster_id=$1`, [params.id]).then(el => el.rows?.[0])
50
+ || await pg.query(`select *, geom::box2d as bounds, 'css' as source_type from gis.cartocss where cartocss_id=$1`, [params.id]).then(el => el.rows?.[0]);
51
+
52
+ if (!data) {
53
+ return reply.status(404).send({ error: 'not found', code: 404 });
54
+ }
55
+
56
+ const send = eventStream(reply);
57
+
58
+ try {
59
+ const relpath = data.source_type === 'raster' ? ['raster', config.mapnik?.folder, data.source_path].filter(Boolean).join('/') : null;
60
+ const name = data.source_type === 'css' ? ['vector', config.mapnik?.folder || '', data.source_path || params.id].filter(Boolean).join('/') : null;
61
+
62
+ // refresh extent
63
+ const bounds = data.source_type === 'css'
64
+ ? await cartoBounds({ id: data.cartocss_id, dataset: data.config/* , table: data.card_table */ }, pg)
65
+ : data.bounds?.replace?.(')', '').substr(4).split(/[, ]/g).map((el) => el - 0);
66
+
67
+ send(`start: ${data.name} ${params.id} ${bounds} ${data.srid} ${data.proj4}`);
68
+
69
+ if (!bounds) {
70
+ return send('geom is not set');
71
+ }
72
+
73
+ bounds[0] = Math.max(bounds[0], maxBounds[0]);
74
+ bounds[1] = Math.max(bounds[1], maxBounds[1]);
75
+
76
+ bounds[2] = Math.min(bounds[2], maxBounds[2]);
77
+ bounds[3] = Math.min(bounds[3], maxBounds[3]);
78
+
79
+ send({
80
+ bounds, minzoom: zoom, maxzoom: max, maxBounds,
81
+ });
82
+
83
+ const tiles = await convertBoundToTile({
84
+ bounds, minzoom: zoom, maxzoom: max, mercator,
85
+ });
86
+
87
+ send(tiles);
88
+
89
+ const tileLen = tiles.reduce((acc, el) => acc + el.count, 0);
90
+
91
+ if (tileLen > MAX_LIMIT) {
92
+ send({ MAX_LIMIT });
93
+ }
94
+
95
+ let tileNum = 0;
96
+
97
+ const tasks = tiles.flatMap((item) => {
98
+ const {
99
+ maxY, minY, minX, maxX, z,
100
+ } = item;
101
+
102
+ const xs = Array.from({ length: maxX - minX + 1 }, (_, i) => minX + i);
103
+
104
+ return xs.flatMap((x) => {
105
+ const ys = Array.from({ length: maxY - minY + 1 }, (_, i) => minY + i);
106
+
107
+ return ys.map((y) => async () => {
108
+ if (tileNum > MAX_LIMIT) return;
109
+
110
+ const tilePath = `${params.id}/${z}/${x}/${y}.png`;
111
+ send(`Start ${tileNum + 1}/${tileLen} ${tilePath}`);
112
+
113
+ const time = Date.now();
114
+
115
+ const bbox = mercator.bbox(x, y, z, false, '900913');
116
+ const render = await RenderTile({ path: relpath, name, bbox });
117
+
118
+ if (render?.err) {
119
+ send(render.err);
120
+ return;
121
+ }
122
+
123
+ send(
124
+ `${tileNum + 1}/${tileLen} ${config.local || config.debug ? render.tile_path : params.id} len:${render.base64.length} cache: ${!!render?.cache} time:${Date.now() - time}ms`,
125
+ );
126
+ tileNum += 1;
127
+ });
128
+ });
129
+ });
130
+
131
+ await runPool(tasks, CONCURRENCY);
132
+
133
+ send('OK');
134
+ return 'OK';
135
+ }
136
+ catch (err) {
137
+ const error = config.local || config.debug ? err.toString() : 'pretile error';
138
+ send(error);
139
+ logger.file('pretile.error', { error: err.toString(), stack: err.stack, id: params.id });
140
+ return reply.status(500).send({ error, code: 500 });
141
+ }
142
+ finally {
143
+ send('finish', true);
144
+ }
145
+ }
@@ -36,7 +36,6 @@ export default async function rasterInfo({
36
36
  const { data, cache, error } = await GetRasterInfo({
37
37
  path: relpath,
38
38
  proj4,
39
- ttl: query.nocache ? '0' : '1h',
40
39
  }).catch(err => ({ error: err.toString() }));
41
40
 
42
41
  if (query.debug) {
@@ -6,8 +6,8 @@ export default async function cartoBounds({ id, dataset, table }, pg = pgClients
6
6
  }
7
7
 
8
8
  const sqlBounds = dataset
9
- ? dataset.map(el => ({ tbl: el.table.replace(/"/g, "").split('.'), geom: el.gcol || 'geom' })).map(({ tbl, geom }) => `select ST_Transform(ST_SetSRID( ST_EstimatedExtent('${tbl[0]}','${tbl[1]}', '${geom}'), (SELECT st_srid(${geom}) from ${tbl.join('.')} limit 1)),4326)`)
10
- : [`select ST_Transform(ST_SetSRID(ST_EstimatedExtent('${table.replace(/"/g, "").split('.')[0]}', '${table.replace(/"/g, "").split('.')[1]}', 'geom'),(SELECT st_srid(geom) from ${table} limit 1)),4326)`];
9
+ ? dataset.map(el => ({ tbl: el.table.replace(/"/g, "").split('.'), geom: el.gcol || 'geom' })).map(({ tbl, geom }) => `select ST_Transform(ST_SetSRID( ST_EstimatedExtent('${tbl[0]}','${tbl[1]}', '${geom}'), (SELECT st_srid(${geom}) from ${tbl[0]}."${tbl[1]}" limit 1)),4326)`)
10
+ : [`select ST_Transform(ST_SetSRID(ST_EstimatedExtent('${table.replace(/"/g, "").split('.')[0]}', '${table.replace(/"/g, "").split('.')[1]}', 'geom'),(SELECT st_srid(geom) from ${table.split('.')[0]}."${table.split('.')[1]}" limit 1)),4326)`];
11
11
 
12
12
  const geom = await pg.query(
13
13
  `update gis.cartocss set
@@ -0,0 +1,27 @@
1
+ export default async function boundsToTiles({
2
+ bounds, minzoom, maxzoom, mercator,
3
+ }) {
4
+ if (!bounds) return { error: 'param bounds is required', status: 400 };
5
+ if (!minzoom) return { error: 'param minzoom is required ', status: 400 };
6
+ if (!maxzoom) return { error: 'param maxzoom is required ', status: 400 };
7
+
8
+ const minzoom1 = minzoom - 0;
9
+ const maxzoom1 = maxzoom - 0;
10
+
11
+ if (maxzoom1 < minzoom1) {
12
+ return { error: 'maxzoom must be >= minzoom', status: 400 };
13
+ }
14
+
15
+ const arr = Array.from(
16
+ { length: maxzoom1 - minzoom1 + 1 },
17
+ (_, i) => minzoom1 + i,
18
+ );
19
+
20
+ const TILE = arr.reduce((prev, z) => {
21
+ const convert = mercator.convert(Array.isArray(bounds) ? bounds : bounds.split(','), '900913');
22
+ const XY = mercator.xyz(convert, z, false, '900913');
23
+ prev.push({ ...XY, z, count: (XY.maxX - XY.minX + 1) * (XY.maxY - XY.minY + 1) });
24
+ return prev;
25
+ }, []);
26
+ return TILE;
27
+ }
@@ -8,11 +8,23 @@ import readDir from './controllers/readDir.js';
8
8
  import fileStat from './controllers/fileStat.js';
9
9
  import fileSearch from './controllers/fileSearch.js';
10
10
  import clearTiles from './controllers/clearTiles.js';
11
+ import pretile from './controllers/pretile.js';
11
12
 
12
13
  const publicParams = { config: { policy: 'L0' }, package: 'gis' }; // L0 === public
13
14
  const adminParams = { config: { policy: 'L1', role: 'admin' }, package: 'gis' };
14
15
  const params = { config: { policy: 'L1' }, package: 'gis' }; // L1 === authorized only
15
16
 
17
+ const pretileSchema = {
18
+ querystring: {
19
+ type: "object",
20
+ properties: {
21
+ zoom: { type: "number", exclusiveMinimum: 0, maximum: 22 },
22
+ max: { type: "number", exclusiveMinimum: 0, maximum: 22 },
23
+ },
24
+ required: ["zoom"],
25
+ },
26
+ };
27
+
16
28
  export default async function route(app) {
17
29
  app.get('/gis-upload-raster/:id', params, uploadRaster);
18
30
  app.get('/gis-xml/:id', publicParams, createXml);
@@ -24,4 +36,5 @@ export default async function route(app) {
24
36
  app.get('/gis-file-info', adminParams, fileStat);
25
37
  app.get('/gis-file-search', adminParams, fileSearch);
26
38
  app.get('/gis-clear-rtile/:id', adminParams, clearTiles);
39
+ app.get('/gis-pretile/:id', { ...adminParams, schema: pretileSchema }, pretile);
27
40
  }