geokernel-electron 1.0.7 → 1.0.9

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.
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geokernel-electron",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Electron bindings for the GeoKernel GIS SDK.",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
package/src/runtime.js CHANGED
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
2
 
3
+ const crypto = require("crypto");
3
4
  const fs = require("fs");
5
+ const os = require("os");
4
6
  const path = require("path");
5
7
 
8
+ const EXCLUDED_GDAL_PLUGIN_NAMES = new Set([
9
+ "gdal_ECW_JP2ECW.dll",
10
+ "gdal_MrSID.dll",
11
+ ]);
12
+
6
13
  function packageRoot() {
7
14
  return path.resolve(__dirname, "..");
8
15
  }
@@ -42,24 +49,26 @@ function configureRuntimeEnvironment(binDir) {
42
49
 
43
50
  const assetsDir = path.join(packageRoot(), "assets", "images");
44
51
  if (fs.existsSync(assetsDir)) {
45
- process.env.GEOKERNEL_ICON_DIR ||= assetsDir;
52
+ process.env.GEOKERNEL_ICON_DIR = assetsDir;
46
53
  }
47
54
 
48
55
  const gdalData = path.join(binDir, "gdal-data");
49
56
  if (fs.existsSync(gdalData)) {
50
- process.env.GDAL_DATA ||= gdalData;
57
+ process.env.GDAL_DATA = gdalData;
51
58
  }
52
59
 
53
60
  const projData = path.join(binDir, "proj-data");
54
61
  if (fs.existsSync(projData)) {
55
- process.env.PROJ_LIB ||= projData;
62
+ process.env.PROJ_LIB = projData;
56
63
  }
57
64
 
58
65
  const gdalPlugins = path.join(binDir, "gdalplugins");
59
66
  if (fs.existsSync(gdalPlugins)) {
60
- process.env.GDAL_DRIVER_PATH ||= gdalPlugins;
67
+ process.env.GDAL_DRIVER_PATH = prepareGdalPluginDir(gdalPlugins);
61
68
  }
62
69
 
70
+ configureNativeGdalOptions(binDir);
71
+
63
72
  const qtPlugins = firstExistingDirectory([
64
73
  path.join(binDir, "plugins"),
65
74
  binDir,
@@ -74,6 +83,82 @@ function configureRuntimeEnvironment(binDir) {
74
83
  }
75
84
  }
76
85
 
86
+ function prepareGdalPluginDir(sourceDir) {
87
+ const targetDir = path.join(gdalPluginCacheRoot(), pluginCacheKey(sourceDir));
88
+ fs.mkdirSync(targetDir, { recursive: true });
89
+
90
+ const expectedNames = new Set(
91
+ fs.readdirSync(sourceDir)
92
+ .filter((name) => name.toLowerCase().endsWith(".dll"))
93
+ .filter((name) => !EXCLUDED_GDAL_PLUGIN_NAMES.has(name)),
94
+ );
95
+
96
+ for (const name of fs.readdirSync(targetDir)) {
97
+ if (name.toLowerCase().endsWith(".dll") && !expectedNames.has(name)) {
98
+ fs.rmSync(path.join(targetDir, name), { force: true });
99
+ }
100
+ }
101
+
102
+ for (const name of expectedNames) {
103
+ const source = path.join(sourceDir, name);
104
+ const target = path.join(targetDir, name);
105
+ if (shouldCopyPlugin(source, target)) {
106
+ fs.copyFileSync(source, target);
107
+ const sourceStat = fs.statSync(source);
108
+ fs.utimesSync(target, sourceStat.atime, sourceStat.mtime);
109
+ }
110
+ }
111
+
112
+ return targetDir;
113
+ }
114
+
115
+ function gdalPluginCacheRoot() {
116
+ const base = process.platform === "win32" && process.env.LOCALAPPDATA
117
+ ? process.env.LOCALAPPDATA
118
+ : os.homedir();
119
+
120
+ return path.join(base, "GeoKernel", "Electron", "gdalplugins");
121
+ }
122
+
123
+ function pluginCacheKey(sourceDir) {
124
+ return crypto
125
+ .createHash("sha1")
126
+ .update(path.resolve(sourceDir), "utf8")
127
+ .digest("hex")
128
+ .slice(0, 12);
129
+ }
130
+
131
+ function shouldCopyPlugin(source, target) {
132
+ if (!fs.existsSync(target)) {
133
+ return true;
134
+ }
135
+
136
+ const sourceStat = fs.statSync(source);
137
+ const targetStat = fs.statSync(target);
138
+ return sourceStat.size !== targetStat.size || sourceStat.mtimeMs > targetStat.mtimeMs;
139
+ }
140
+
141
+ function configureNativeGdalOptions(binDir) {
142
+ const gdalDll = path.join(binDir, "gdal.dll");
143
+ if (!fs.existsSync(gdalDll)) {
144
+ return;
145
+ }
146
+
147
+ try {
148
+ const koffi = require("koffi");
149
+ const gdal = koffi.load(gdalDll);
150
+ const setConfigOption = gdal.func("CPLSetConfigOption", "void", ["str", "str"]);
151
+
152
+ setConfigOption("GDAL_DRIVER_PATH", process.env.GDAL_DRIVER_PATH || "");
153
+ setConfigOption("GDAL_DATA", process.env.GDAL_DATA || "");
154
+ setConfigOption("PROJ_DATA", process.env.PROJ_LIB || "");
155
+ setConfigOption("PROJ_LIB", process.env.PROJ_LIB || "");
156
+ } catch {
157
+ // GeoKernel.Viewer can still load without eagerly touching GDAL. Any real
158
+ // GDAL load error will be reported by the SDK when a layer is opened.
159
+ }
160
+ }
161
+
77
162
  module.exports = {
78
163
  configureRuntimeEnvironment,
79
164
  findBinDir,