signalk-charts-provider-simple 2.3.3 → 2.3.4
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.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -7
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/catalog-manager.d.ts.map +1 -1
- package/dist/utils/catalog-manager.js.map +1 -1
- package/dist/utils/file-scanner.d.ts.map +1 -1
- package/dist/utils/file-scanner.js.map +1 -1
- package/dist/utils/mbtiles-metadata.d.ts.map +1 -1
- package/dist/utils/mbtiles-metadata.js.map +1 -1
- package/dist/utils/mbtiles-reader.d.ts.map +1 -1
- package/dist/utils/mbtiles-reader.js.map +1 -1
- package/dist/utils/path-safety.d.ts +75 -0
- package/dist/utils/path-safety.d.ts.map +1 -1
- package/dist/utils/path-safety.js +76 -0
- package/dist/utils/path-safety.js.map +1 -1
- package/dist/utils/s57-converter.d.ts +27 -0
- package/dist/utils/s57-converter.d.ts.map +1 -1
- package/dist/utils/s57-converter.js +88 -8
- package/dist/utils/s57-converter.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmHxD,OAAO,KAAK,EACV,aAAa,EAEb,iBAAiB,EAIjB,QAAQ,EAET,MAAM,YAAY,CAAC;AAepB,QAAA,MAAM,iBAAiB,GAAI,KAAK,iBAAiB,KAAG,MA+5GnD,CAAC;AA4GF,eAAO,MAAM,oBAAoB,GAC/B,KAAK,QAAQ,EACb,UAAU,aAAa,EACvB,GAAG,MAAM,EACT,GAAG,MAAM,EACT,GAAG,MAAM,KACR,IAiDF,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { repairMbtilesMetadata, setMbtilesDisplayName } from './utils/mbtiles-me
|
|
|
18
18
|
import { open as openMbtilesReader } from './utils/mbtiles-reader.js';
|
|
19
19
|
import { writeChartPathMarker } from './utils/path-marker.js';
|
|
20
20
|
import { getBlankTileReplacement, getOverzoomedTile } from './utils/tile-overzoom.js';
|
|
21
|
-
import { arePairWithinBase, isWithinBase, validateChartName } from './utils/path-safety.js';
|
|
21
|
+
import { arePairWithinBase, classifyChartDirAccess, hasHostChartsMountEnv, isHostMountPath, isWithinBase, resolveDefaultChartsPath, validateChartName } from './utils/path-safety.js';
|
|
22
22
|
import { parsePluginConfig } from './utils/plugin-config-schema.js';
|
|
23
23
|
import { cleanupQuarantineDir, makeQuarantineDir, promoteQuarantine, sweepStaleQuarantineDirs } from './utils/quarantine.js';
|
|
24
24
|
import { parseBody, parseShape } from './utils/rest-validation.js';
|
|
@@ -51,12 +51,21 @@ const pluginConstructor = (app) => {
|
|
|
51
51
|
let pluginDataDir = '';
|
|
52
52
|
let defaultChartsPath = '';
|
|
53
53
|
let serverMajorVersion = 1;
|
|
54
|
+
// The effective default chart directory. When Signal K runs in a container
|
|
55
|
+
// (signalk-universal-installer), the installer can mount a host folder the
|
|
56
|
+
// user shares with other chart apps (OpenCPN/qtVlm/...) and inject its
|
|
57
|
+
// in-container path via SIGNALK_CHARTS_HOST_PATH. When that env is present we
|
|
58
|
+
// default to it instead of the in-data-volume `charts-simple` dir, so a
|
|
59
|
+
// container user gets the shared host folder out of the box with no config —
|
|
60
|
+
// and so the chartPath field is never the free-text foot-gun that pointed at
|
|
61
|
+
// an unmounted host path. A user can still override via the chartPath setting.
|
|
54
62
|
function getDefaultChartsPath() {
|
|
55
63
|
if (!defaultChartsPath) {
|
|
56
64
|
pluginDataDir = app.getDataDirPath();
|
|
57
|
-
const configBasePath = path.dirname(path.dirname(pluginDataDir));
|
|
58
|
-
defaultChartsPath = path.join(configBasePath, 'charts-simple');
|
|
59
65
|
serverMajorVersion = app.config?.version ? parseInt(app.config.version.split('.')[0], 10) : 1;
|
|
66
|
+
const configBasePath = path.dirname(path.dirname(pluginDataDir));
|
|
67
|
+
const inDataVolumeDefault = path.join(configBasePath, 'charts-simple');
|
|
68
|
+
defaultChartsPath = resolveDefaultChartsPath(process.env.SIGNALK_CHARTS_HOST_PATH, inDataVolumeDefault);
|
|
60
69
|
}
|
|
61
70
|
return defaultChartsPath;
|
|
62
71
|
}
|
|
@@ -70,7 +79,11 @@ const pluginConstructor = (app) => {
|
|
|
70
79
|
chartPath: {
|
|
71
80
|
type: 'string',
|
|
72
81
|
title: 'Chart path',
|
|
73
|
-
description:
|
|
82
|
+
description: (hasHostChartsMountEnv(process.env.SIGNALK_CHARTS_HOST_PATH)
|
|
83
|
+
? `Main directory for chart files. Defaults to the shared host charts folder mounted by the installer. ` +
|
|
84
|
+
`Leave this blank to use it; only change it if you know the path is reachable inside the container. `
|
|
85
|
+
: `Main directory for chart files. Defaults to "${getDefaultChartsPath()}". `) +
|
|
86
|
+
`Subfolders will be scanned recursively.`,
|
|
74
87
|
default: getDefaultChartsPath()
|
|
75
88
|
},
|
|
76
89
|
cpuBudget: {
|
|
@@ -179,10 +192,53 @@ const pluginConstructor = (app) => {
|
|
|
179
192
|
props = { ...config };
|
|
180
193
|
setCpuBudget(props.cpuBudget);
|
|
181
194
|
getDefaultChartsPath(); // ensure lazy init
|
|
182
|
-
ensureDirectoryExists(defaultChartsPath);
|
|
183
195
|
const chartPath = props.chartPath || defaultChartsPath;
|
|
184
|
-
|
|
185
|
-
|
|
196
|
+
// Is the effective path the host folder the installer bind-mounted (via
|
|
197
|
+
// SIGNALK_CHARTS_HOST_PATH)? If so we must NOT create it on demand: that
|
|
198
|
+
// folder is supposed to already exist (the installer made it and mounted
|
|
199
|
+
// it), so a missing dir means a missing mount — and `mkdir`-ing it would
|
|
200
|
+
// silently shadow the absent mount with an ephemeral in-container dir whose
|
|
201
|
+
// charts vanish on container recreate. isHostMountPath normalizes both
|
|
202
|
+
// sides so a trailing slash / `.`/`..` can't divert the mount into the
|
|
203
|
+
// mkdir branch.
|
|
204
|
+
const isHostMount = isHostMountPath(chartPath, process.env.SIGNALK_CHARTS_HOST_PATH);
|
|
205
|
+
let exists;
|
|
206
|
+
let createdOrWritable;
|
|
207
|
+
if (isHostMount) {
|
|
208
|
+
// Probe, never create.
|
|
209
|
+
exists = fs.existsSync(chartPath);
|
|
210
|
+
createdOrWritable = exists && isDirWritable(chartPath);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// In-data-volume default or a user-typed path: create-on-demand, then
|
|
214
|
+
// verify it is an actually-writable directory. ensureDirectoryExists
|
|
215
|
+
// returns true for any path that already exists, so without the
|
|
216
|
+
// isDirWritable probe an existing read-only dir (or a regular file at
|
|
217
|
+
// that path) would slip through as usable and only fail on first write.
|
|
218
|
+
createdOrWritable = ensureDirectoryExists(chartPath) && isDirWritable(chartPath);
|
|
219
|
+
exists = fs.existsSync(chartPath);
|
|
220
|
+
}
|
|
221
|
+
const access = classifyChartDirAccess(isHostMount, exists, createdOrWritable);
|
|
222
|
+
if (!access.ok) {
|
|
223
|
+
if (access.reason === 'mount-missing') {
|
|
224
|
+
// NB: clearing the Chart path setting does NOT help here — with
|
|
225
|
+
// SIGNALK_CHARTS_HOST_PATH still set, the default resolves right back to
|
|
226
|
+
// this same (missing) mount. The real fixes are restoring the mount or
|
|
227
|
+
// removing the installer env / pointing at a reachable in-container dir.
|
|
228
|
+
app.setPluginError(`Shared charts folder is not mounted into the container at ${chartPath}. ` +
|
|
229
|
+
`Charts live in a host folder the installer shares with the container; that ` +
|
|
230
|
+
`mount appears to be missing. Re-run the installer to restore it, remove the ` +
|
|
231
|
+
`installer-provided SIGNALK_CHARTS_HOST_PATH setting, or set Chart path to a ` +
|
|
232
|
+
`directory that is reachable inside the container.`);
|
|
233
|
+
}
|
|
234
|
+
else if (access.reason === 'exists-unwritable') {
|
|
235
|
+
app.setPluginError(`Chart directory exists but is not writable by Signal K: ${chartPath}. ` +
|
|
236
|
+
`In a container this is usually a folder-ownership mismatch — make sure the ` +
|
|
237
|
+
`host folder is owned by the user that runs Signal K.`);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
app.setPluginError(`Chart directory is not writable: ${chartPath}`);
|
|
241
|
+
}
|
|
186
242
|
app.setPluginStatus('Started (no chart directory)');
|
|
187
243
|
return;
|
|
188
244
|
}
|
|
@@ -2895,6 +2951,25 @@ const ensureDirectoryExists = (dirPath) => {
|
|
|
2895
2951
|
return false;
|
|
2896
2952
|
}
|
|
2897
2953
|
};
|
|
2954
|
+
// Probe whether an EXISTING directory is usable as a chart root, without
|
|
2955
|
+
// creating it. Used for the injected host charts mount: we must NOT mkdir a
|
|
2956
|
+
// missing mount (that silently shadows it with an ephemeral in-container dir),
|
|
2957
|
+
// so we check existence + usability separately instead of create-on-demand.
|
|
2958
|
+
// Requires an actual directory (W_OK alone would accept a writable regular
|
|
2959
|
+
// file) with both write AND execute/search permission (X_OK — needed to
|
|
2960
|
+
// traverse into it to read/write chart files).
|
|
2961
|
+
const isDirWritable = (dirPath) => {
|
|
2962
|
+
try {
|
|
2963
|
+
if (!fs.statSync(dirPath).isDirectory()) {
|
|
2964
|
+
return false;
|
|
2965
|
+
}
|
|
2966
|
+
fs.accessSync(dirPath, fs.constants.W_OK | fs.constants.X_OK);
|
|
2967
|
+
return true;
|
|
2968
|
+
}
|
|
2969
|
+
catch {
|
|
2970
|
+
return false;
|
|
2971
|
+
}
|
|
2972
|
+
};
|
|
2898
2973
|
const cleanupEmptyParents = (deletedPath, stopAt) => {
|
|
2899
2974
|
try {
|
|
2900
2975
|
let parent = path.dirname(deletedPath);
|