@eodash/eodash 5.2.0 → 5.3.0

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 (119) hide show
  1. package/core/client/components/DashboardLayout.vue +0 -1
  2. package/core/client/composables/index.js +53 -59
  3. package/core/client/eodashSTAC/EodashCollection.js +196 -94
  4. package/core/client/eodashSTAC/auth.js +86 -0
  5. package/core/client/eodashSTAC/createLayers.js +204 -4
  6. package/core/client/eodashSTAC/helpers.js +258 -58
  7. package/core/client/eodashSTAC/parquet.js +0 -13
  8. package/core/client/eodashSTAC/triggers.js +1 -1
  9. package/core/client/store/actions.js +14 -0
  10. package/core/client/store/stac.js +46 -8
  11. package/core/client/store/states.js +6 -0
  12. package/core/client/types.ts +206 -3
  13. package/core/client/utils/bands-editor/arithmetic.js +144 -0
  14. package/core/client/utils/bands-editor/colors.js +36 -0
  15. package/core/client/utils/bands-editor/dom.js +196 -0
  16. package/core/client/utils/bands-editor/exampleSchema.json +1320 -0
  17. package/core/client/utils/bands-editor/index.js +68 -0
  18. package/core/client/utils/bands-editor/rgb.js +102 -0
  19. package/core/client/utils/index.js +5 -2
  20. package/core/client/views/Dashboard.vue +1 -1
  21. package/core/client/vite-env.d.ts +122 -0
  22. package/dist/client/{DashboardLayout-Dq9Kfe6O.js → DashboardLayout-Cq15p4TH.js} +4 -5
  23. package/dist/client/{DynamicWebComponent-DCBMXskE.js → DynamicWebComponent-Cv-fPRG1.js} +1 -1
  24. package/dist/client/{EodashDatePicker-DtngxU6s.js → EodashDatePicker-CPlJwEIO.js} +20 -22
  25. package/dist/client/{EodashItemFilter-ClQebJQt.js → EodashItemFilter-Ydebgbjj.js} +46 -31
  26. package/dist/client/EodashLayerControl-COhrkNEs.js +1517 -0
  27. package/dist/client/{EodashLayoutSwitcher-DQ8SfVDd.js → EodashLayoutSwitcher-pnKhTRZV.js} +4 -4
  28. package/dist/client/EodashMapBtns-Cj0Fx119.js +301 -0
  29. package/dist/client/{EodashStacInfo-Dt1nF06x.js → EodashStacInfo-Dadkg_Nj.js} +1 -1
  30. package/dist/client/EodashTimeSlider-CpoHX0S7.js +53 -0
  31. package/dist/client/{EodashTools-DV5ykmWc.js → EodashTools-UGBG7KC9.js} +10 -7
  32. package/dist/client/{ExportState-B6zZQUmE.js → ExportState-GtJkAqeZ.js} +145 -120
  33. package/dist/client/{Footer-DNhXs8k6.js → Footer-D3ZPG5c4.js} +1 -1
  34. package/dist/client/{Header-BjhN5JY4.js → Header-z6AK-wpN.js} +2 -2
  35. package/dist/client/MobileLayout-BXNsNftb.js +118 -0
  36. package/dist/client/{PopUp-CgpvNr3o.js → PopUp-BbQdjENV.js} +79 -43
  37. package/dist/client/{ProcessList-vecpxThi.js → ProcessList-C6VsdsYI.js} +5 -6
  38. package/dist/client/{VImg-CETuikH2.js → VImg-CxaMSB99.js} +6 -3
  39. package/dist/client/{VMain-Ci9DyaGU.js → VMain-Ds7yw0wj.js} +1 -1
  40. package/dist/client/{VTooltip-J4ac48X7.js → VTooltip-Cze6CEVh.js} +2 -2
  41. package/dist/client/{WidgetsContainer-CCML4TyV.js → WidgetsContainer-D66bj-JJ.js} +1 -1
  42. package/dist/client/asWebComponent-CWbNRdf9.js +8895 -0
  43. package/dist/client/{async-B7jIrM53.js → async-BA7oWCMX.js} +2 -2
  44. package/dist/client/easing-CH0-9wR8.js +35 -0
  45. package/dist/client/eo-dash.js +1 -1
  46. package/dist/client/{forwardRefs-BQclvjMq.js → forwardRefs-BUfxOIo-.js} +58 -45
  47. package/dist/client/{handling-BS24aG1q.js → handling-DlNTtKB-.js} +12 -6
  48. package/dist/client/{helpers-wXK7Ywio.js → helpers-CtE0W7iu.js} +572 -277
  49. package/dist/client/{index-4UCzZi8B.js → index-CeEZIjO6.js} +26 -13
  50. package/dist/client/{index-B2XpdgR6.js → index-CsKbRDeN.js} +63 -36
  51. package/dist/client/{index-9KR-G20t.js → index-D4_NRKrf.js} +2 -2
  52. package/dist/client/index-DeECc3lV.js +571 -0
  53. package/dist/client/templates.js +82 -15
  54. package/dist/client/{transition-yBii4fu6.js → transition-Byvp3L6Y.js} +1 -1
  55. package/dist/node/cli.js +6 -6
  56. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +24 -10
  57. package/dist/types/core/client/eodashSTAC/auth.d.ts +7 -0
  58. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +15 -3
  59. package/dist/types/core/client/eodashSTAC/helpers.d.ts +46 -15
  60. package/dist/types/core/client/plugins/vuetify.d.ts +14 -14
  61. package/dist/types/core/client/store/actions.d.ts +2 -0
  62. package/dist/types/core/client/store/stac.d.ts +16 -7
  63. package/dist/types/core/client/store/states.d.ts +4 -0
  64. package/dist/types/core/client/types.d.ts +170 -2
  65. package/dist/types/core/client/utils/bands-editor/arithmetic.d.ts +8 -0
  66. package/dist/types/core/client/utils/bands-editor/colors.d.ts +15 -0
  67. package/dist/types/core/client/utils/bands-editor/dom.d.ts +42 -0
  68. package/dist/types/core/client/utils/bands-editor/index.d.ts +20 -0
  69. package/dist/types/core/client/utils/bands-editor/rgb.d.ts +15 -0
  70. package/dist/types/core/client/utils/index.d.ts +1 -1
  71. package/dist/types/templates/baseConfig.d.ts +87 -1
  72. package/dist/types/templates/expert.d.ts +6 -6
  73. package/dist/types/templates/explore.d.ts +67 -0
  74. package/dist/types/templates/index.d.ts +1 -1
  75. package/dist/types/templates/{light.d.ts → lite.d.ts} +5 -5
  76. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +21 -0
  77. package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +49 -0
  78. package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +4 -0
  79. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +12 -0
  80. package/dist/types/widgets/EodashItemCatalog/types.d.ts +14 -0
  81. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +2 -0
  82. package/dist/types/widgets/EodashMap/index.vue.d.ts +108 -2
  83. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
  84. package/dist/types/widgets/EodashMap/methods/index.d.ts +1 -1
  85. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
  86. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +7 -0
  87. package/dist/types/widgets/EodashTools.vue.d.ts +10 -10
  88. package/dist/types/widgets/ExportState.vue.d.ts +2 -0
  89. package/package.json +28 -27
  90. package/templates/baseConfig.js +10 -5
  91. package/templates/compare.js +2 -2
  92. package/templates/expert.js +5 -5
  93. package/templates/explore.js +62 -0
  94. package/templates/index.js +1 -1
  95. package/templates/{light.js → lite.js} +1 -1
  96. package/widgets/EodashDatePicker.vue +15 -18
  97. package/widgets/EodashItemCatalog/index.vue +161 -0
  98. package/widgets/EodashItemCatalog/methods/filters.js +216 -0
  99. package/widgets/EodashItemCatalog/methods/handlers.js +50 -0
  100. package/widgets/EodashItemCatalog/methods/map.js +144 -0
  101. package/widgets/EodashItemCatalog/types.ts +15 -0
  102. package/widgets/EodashItemFilter.vue +35 -28
  103. package/widgets/EodashLayerControl.vue +10 -6
  104. package/widgets/EodashLayoutSwitcher.vue +1 -1
  105. package/widgets/EodashMap/EodashMapBtns.vue +18 -9
  106. package/widgets/EodashMap/index.vue +22 -12
  107. package/widgets/EodashMap/methods/create-layers-config.js +9 -6
  108. package/widgets/EodashMap/methods/index.js +27 -13
  109. package/widgets/EodashProcess/index.vue +17 -1
  110. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +9 -3
  111. package/widgets/EodashProcess/methods/handling.js +2 -0
  112. package/widgets/EodashProcess/methods/outputs.js +1 -0
  113. package/widgets/EodashTimeSlider.vue +40 -0
  114. package/widgets/EodashTools.vue +7 -3
  115. package/widgets/ExportState.vue +53 -22
  116. package/dist/client/EodashLayerControl-BLBds28C.js +0 -154
  117. package/dist/client/EodashMapBtns-B89_YBDw.js +0 -326
  118. package/dist/client/MobileLayout-JelB6w1G.js +0 -118
  119. package/dist/client/asWebComponent-ZyEzWOOf.js +0 -19092
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Generic handler for possible authentications schemes as defined in STAC authentication extension.
3
+ * @param {import("@/types").StacAuthItem } item
4
+ * @param {import("@/types").StacAuthLink | import("@/types").StacAuthAsset} linkOrAsset
5
+ * @returns {string}
6
+ */
7
+ export function handleAuthenticationOfLink(item, linkOrAsset) {
8
+ // browse through all authentication refs on a link to find a first one we support
9
+ for (const authRef of linkOrAsset["auth:refs"] || []) {
10
+ const authSchemes = item["auth:schemes"];
11
+ if (authRef in authSchemes) {
12
+ switch (authSchemes[authRef].type) {
13
+ case "apiKey": {
14
+ //@ts-expect-error TODO
15
+ return handleApiKeyBasedAuth(authSchemes[authRef], linkOrAsset.href);
16
+ }
17
+ // case "signedUrl":
18
+ // case "s3":
19
+ // case "http":
20
+ // case "openIdConnect":
21
+ // case "apiKey":
22
+ // case "oauth2":
23
+ // todo add more handlers when needed
24
+ default:
25
+ console.error(`eodash does not support referenced authentication scheme ${authRef}`);
26
+ }
27
+ }
28
+ }
29
+ return linkOrAsset.href;
30
+ }
31
+ /**
32
+ * Generic handler for possible authentications schemes as defined in STAC authentication extension.
33
+ * @param {import("@/types").ApiKeyAuthScheme } schemeDef
34
+ * @param { string } href
35
+ * @returns { string }
36
+ */
37
+ function handleApiKeyBasedAuth(schemeDef, href) {
38
+ // add token to query parameters of href
39
+ let url = href;
40
+ switch (schemeDef.in) {
41
+ case "query": {
42
+ const apiKey = schemeDef.name;
43
+ const envVar = "EODASH_" + apiKey;
44
+ const envValue = process.env[envVar];
45
+ if (envValue) {
46
+ url = setQueryParam(href, apiKey, envValue);
47
+ } else {
48
+ console.error(`env variable ${envVar} for authentication parameter ${apiKey} not set`);
49
+ }
50
+ break
51
+ }
52
+ default:
53
+ console.error('eodash does not support any referenced handler');
54
+ }
55
+ return url;
56
+ }
57
+
58
+ /**
59
+ * Inserts or replaces a query parameter in a URL string (without escaping special characters).
60
+ *
61
+ * @param {string} url - Input URL (may contain special characters)
62
+ * @param {string} key - Query parameter key (e.g. "token", "authCode")
63
+ * @param {string} value - Value to set for the key
64
+ * @returns {string} - Updated URL string
65
+ */
66
+ function setQueryParam(url, key, value) {
67
+ // Split off any fragment (#something)
68
+ const [base, hash] = url.split("#", 2);
69
+
70
+ // Regex to detect existing key, respecting ? or &
71
+ const pattern = new RegExp(`([?&])${key}=[^&#]*`, "i");
72
+
73
+ if (pattern.test(base)) {
74
+ // Replace existing key=value
75
+ url = base.replace(pattern, `$1${key}=${value}`);
76
+ } else {
77
+ // Append as new key=value
78
+ const joiner = base.includes("?") ? "&" : "?";
79
+ url = `${base}${joiner}${key}=${value}`;
80
+ }
81
+
82
+ // Reattach fragment if present
83
+ if (hash) url += "#" + hash;
84
+
85
+ return url;
86
+ }
@@ -1,13 +1,17 @@
1
1
  import { registerProjection } from "@/store/actions";
2
2
  import { mapEl } from "@/store/states";
3
+
3
4
  import {
4
5
  extractRoles,
5
6
  getProjectionCode,
6
7
  createLayerID,
7
8
  createAssetID,
8
9
  mergeGeojsons,
10
+ extractLayerConfig,
9
11
  addTooltipInteraction,
12
+ fetchStyle,
10
13
  } from "./helpers";
14
+ import { handleAuthenticationOfLink } from "./auth";
11
15
  import log from "loglevel";
12
16
 
13
17
  /**
@@ -41,7 +45,7 @@ export async function createLayersFromAssets(
41
45
 
42
46
  const geoJsonSources = [];
43
47
  let geoJsonRoles = {};
44
-
48
+ let projection = undefined;
45
49
  for (const [idx, ast] of Object.keys(assets).entries()) {
46
50
  // register projection if exists
47
51
  const assetProjection =
@@ -49,6 +53,7 @@ export async function createLayersFromAssets(
49
53
  assets[ast]?.["proj:epsg"] || assets[ast]?.["eodash:proj4_def"]
50
54
  );
51
55
  await registerProjection(assetProjection);
56
+ projection = getProjectionCode(assetProjection) || "EPSG:4326";
52
57
  if (assets[ast]?.type === "application/geo+json") {
53
58
  geoJsonSources.push(assets[ast].href);
54
59
  geoJsonIdx = idx;
@@ -64,7 +69,7 @@ export async function createLayersFromAssets(
64
69
  source: {
65
70
  type: "FlatGeoBuf",
66
71
  url: assets[ast].href,
67
- format: "GeoJSON",
72
+ projection,
68
73
  attributions: assets[ast].attribution,
69
74
  },
70
75
  properties: {
@@ -131,13 +136,13 @@ export async function createLayersFromAssets(
131
136
  if (geoJsonSources.length) {
132
137
  const assetId = createAssetID(collectionId, item.id, geoJsonIdx);
133
138
  log.debug(`Creating Vector layer from GeoJsons`, assetId);
134
-
139
+ // assumption that each GeoJSON asset is in same projection due to their merging
135
140
  const layer = {
136
141
  type: "Vector",
137
142
  source: {
138
143
  type: "Vector",
139
144
  url: await mergeGeojsons(geoJsonSources),
140
- format: "GeoJSON",
145
+ format: {"type": "GeoJSON", "dataProjection": projection},
141
146
  attributions: geoJsonAttributions,
142
147
  },
143
148
  properties: {
@@ -193,6 +198,7 @@ export async function createLayersFromAssets(
193
198
  * @param {string} collectionId
194
199
  * @param {import('stac-ts').StacItem} item
195
200
  * @param {string} title
201
+ * @param {string} itemUrl
196
202
  * @param {Record<string,any>} [layerDatetime]
197
203
  * @param {object | null} [extraProperties]
198
204
  */
@@ -200,6 +206,7 @@ export const createLayersFromLinks = async (
200
206
  collectionId,
201
207
  title,
202
208
  item,
209
+ itemUrl,
203
210
  layerDatetime,
204
211
  extraProperties,
205
212
  ) => {
@@ -209,6 +216,7 @@ export const createLayersFromLinks = async (
209
216
  const wmsArray = item.links.filter((l) => l.rel === "wms");
210
217
  const wmtsArray = item.links.filter((l) => l.rel === "wmts");
211
218
  const xyzArray = item.links.filter((l) => l.rel === "xyz") ?? [];
219
+ const vectorTileArray = item.links.filter((l) => l.rel === "vector-tile") ?? [];
212
220
 
213
221
  // Taking projection code from main map view, as main view defines
214
222
  // projection for comparison map
@@ -398,5 +406,197 @@ export const createLayersFromLinks = async (
398
406
  }
399
407
  jsonArray.push(json);
400
408
  }
409
+
410
+ for (const vectorTileLink of vectorTileArray ?? []) {
411
+ const vectorTileLinkProjection =
412
+ /** @type {number | string | {name: string, def: string} | undefined} */
413
+ (vectorTileLink?.["proj:epsg"] || vectorTileLink?.["eodash:proj4_def"]);
414
+
415
+ await registerProjection(vectorTileLinkProjection);
416
+ const projectionCode = getProjectionCode(vectorTileLinkProjection || "EPSG:3857");
417
+ const linkId = createLayerID(
418
+ collectionId,
419
+ item.id,
420
+ vectorTileLink,
421
+ viewProjectionCode,
422
+ );
423
+ log.debug("Vector Tile Layer added", linkId);
424
+ const key = /** @type {string | undefined} */ (vectorTileLink["key"]) || undefined;
425
+ // fetch styles and separate them by their mapping between links and assets
426
+ const styles = await fetchStyle(item, itemUrl, key);
427
+ // get the correct style which is not attached to a link
428
+ let { layerConfig, style } = extractLayerConfig(
429
+ linkId ?? "",
430
+ styles,
431
+ );
432
+
433
+ let href = vectorTileLink.href;
434
+ if ("auth:schemes" in item && "auth:refs" in vectorTileLink) {
435
+ href = handleAuthenticationOfLink(/** @type { import("@/types").StacAuthItem} */ (item), /** @type { import("@/types").StacAuthLink} */ (vectorTileLink));
436
+ }
437
+ const json = {
438
+ type: "VectorTile",
439
+ declutter: true,
440
+ properties: {
441
+ id: linkId,
442
+ title: vectorTileLink.title || title || item.id,
443
+ roles: vectorTileLink.roles,
444
+ layerDatetime,
445
+ ...(layerConfig && {
446
+ layerConfig: {
447
+ ...layerConfig,
448
+ style,
449
+ },
450
+ }),
451
+ },
452
+ source: {
453
+ type: "VectorTile",
454
+ format: {
455
+ type: "MVT",
456
+ idProperty: vectorTileLink.idProperty,
457
+ },
458
+ url: href,
459
+ projection: projectionCode,
460
+ attributions: vectorTileLink.attribution,
461
+ },
462
+ interactions: [],
463
+ ...(!style?.variables && { style }),
464
+ };
465
+ addTooltipInteraction(json, style);
466
+ extractRoles(json.properties, vectorTileLink);
467
+ if (extraProperties !== null) {
468
+ json.properties = { ...json.properties, ...extraProperties };
469
+ }
470
+ jsonArray.push(json);
471
+ }
401
472
  return jsonArray;
402
473
  };
474
+ /**
475
+ * Implementation of a function that creates a layer from the render extention
476
+ * @param {import("stac-ts").StacCollection | undefined | null} collection
477
+ * @param {import("stac-ts").StacItem | undefined | null} item
478
+ * @param {string} rasterURL
479
+ * @param {Record<string, any>} [extraProperties]
480
+ * @returns {import("@eox/map/src/layers").EOxLayerType<"Tile","XYZ">[]}
481
+ */
482
+ export function createLayerFromRender(
483
+ rasterURL,
484
+ collection,
485
+ item,
486
+ extraProperties,
487
+ ) {
488
+ if (!collection || !collection.renders || !item) {
489
+ return [];
490
+ }
491
+
492
+ const renders = /** @type {Record<string,import("@/types").Render>} */ (
493
+ collection.renders ?? item?.renders
494
+ );
495
+ const layers = [];
496
+ // special case for rescale
497
+ for (const key in renders) {
498
+ const title = renders[key].title;
499
+
500
+ const assetsCollection =
501
+ renders[key].assets[0] in item["assets"] ? item : collection;
502
+
503
+ const paramsObject = {
504
+ assets: renders[key].assets,
505
+ expression:
506
+ renders[key].expression ??
507
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.expression,
508
+ nodata:
509
+ renders[key].nodata ??
510
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.nodata,
511
+ resampling:
512
+ renders[key].resampling ??
513
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.resampling,
514
+ color_formula:
515
+ renders[key].color_formula ??
516
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.color_formula,
517
+ colormap:
518
+ renders[key].colormap ??
519
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.colormap,
520
+ colormap_name:
521
+ renders[key].colormap_name ??
522
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.colormap_name,
523
+ rescale:
524
+ renders[key].rescale ??
525
+ assetsCollection["assets"]?.[renders[key].assets[0]]?.rescale,
526
+ };
527
+ const paramsStr = encodeURLObject(paramsObject);
528
+ const url = `${rasterURL}/collections/${collection.id}/items/${item.id}/tiles/WebMercatorQuad/{z}/{x}/{y}?${paramsStr}`;
529
+ layers.push({
530
+ /** @type {"Tile"} */
531
+ type: "Tile",
532
+ properties: {
533
+ id: createLayerID(
534
+ collection.id,
535
+ item.id,
536
+ { id: item.id, href: "", title, rel: "" },
537
+ "EPSG:3857",
538
+ ),
539
+ title,
540
+ roles: item.roles,
541
+ ...extraProperties,
542
+ },
543
+ source: {
544
+ /** @type {"XYZ"} */
545
+ type: "XYZ",
546
+ url,
547
+ projection: "EPSG:3857",
548
+ },
549
+ });
550
+ }
551
+
552
+ return layers;
553
+ }
554
+ /**
555
+ *
556
+ * @param {Record<string,any>} obj
557
+ * @returns {string}
558
+ */
559
+ function encodeURLObject(obj) {
560
+ let str = "";
561
+ for (const key in obj) {
562
+ const value = obj[key];
563
+ if (value === null || value === undefined || value === "") {
564
+ continue;
565
+ }
566
+
567
+ const valueType = Array.isArray(value) ? "array" : typeof value;
568
+
569
+ switch (valueType) {
570
+ case "array": {
571
+ // Check if any element in the array is itself an array (multi-dimensional)
572
+ const hasNestedArrays = value.some((/** @type {any} */ item) =>
573
+ Array.isArray(item),
574
+ );
575
+
576
+ if (hasNestedArrays) {
577
+ // For multi-dimensional arrays, repeat the key with different values
578
+ for (const val of value) {
579
+ if (Array.isArray(val)) {
580
+ str += `${key}=${val.join(",")}&`;
581
+ } else {
582
+ str += `${key}=${val}&`;
583
+ }
584
+ }
585
+ } else {
586
+ // For simple arrays, join with commas
587
+ str += `${key}=${value.join(",")}&`;
588
+ }
589
+ break;
590
+ }
591
+ case "object": {
592
+ str += `${key}=${encodeURI(JSON.stringify(value))}&`;
593
+ break;
594
+ }
595
+ default: {
596
+ str += `${key}=${encodeURIComponent(value)}&`;
597
+ break;
598
+ }
599
+ }
600
+ }
601
+ return str;
602
+ }