New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

gpxload

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gpxload - npm Package Compare versions

Comparing version 0.4.1 to 0.5.0

47

package.json
{
"name": "gpxload",
"version": "0.4.1",
"description": "SignalK Server plugin to import / export GPX files and make them available via the SignalK API.",
"main": "src/index.js",
"keywords": [
"signalk-node-server-plugin",
"signalk-webapp",
"signalk"
],
"repository": "https://bitbucket.org/panaaj/signalk-gpx-plugin",
"scripts": {
"format": "prettier-standard 'src/**/*.js'",
"test": "mocha"
},
"author": "AdrianP",
"contributors": [
"name": "gpxload",
"version": "0.5.0",
"description": "GPXLoad: GPX file Import / Export and API plugin for SignalK Server.",
"main": "src/index.js",
"keywords": [
"signalk-node-server-plugin",
"signalk-webapp",
"signalk"
],
"repository": "https://bitbucket.org/panaaj/signalk-gpx-plugin",
"scripts": {
"format": "prettier-standard 'src/**/*.js'",
"test": "mocha"
},
"author": "AdrianP",
"contributors": [
{
"name": "Adrian Panazzolo"
"name": "Adrian Panazzolo"
}
],
"license": "Apache-20",
"dependencies": {
},
"devDependencies": {
],
"license": "Apache-20",
"dependencies": {
"geojson-validation": "^0.2.0"
},
"devDependencies": {
"mocha": "^5.0.5",
"prettier-standard": "^8.0.0"
}
}
}

@@ -1,13 +0,26 @@

# signalk-gpx-plugin
# GPXLoad: signalk-server-plugin
SignalK Plugin and WebApp to enable GPX file import / export.
GPX file Import / Export and API plugin for SignalK Server.
Selected resources in GPX files can be loaded using the Web UI that is accessed via the url: *http://signalk-server/gpxload/*
SignalK server plugin and WebApp that:
- Allows the upload of selected selected Routes, Waypoints and Tracks in GPX files to a SignalK server
Once loaded, the imported routes, waypoints and tracks are made available via the SignalK server http api *http://signalk-server/signalk/v1/api/resources/*.
- Makes uploaded resources available via the SignalK API *e.g. http://signalk-server/signalk/v1/api/reources/routes*
- Preserves the SignalK UUIDs of exported resources written to the GPX file to avoid resource duplication.
Use and Operation:
------------------
**New**
- Added support for SignalK HTTP API PUT actions to enable applications to update / delete resources.
**Breaking Changes:**
- Removed support for resource UUIDs that do not strictly align to the Signal K schema and use the *urn:mrn:signalk:uuid:* prefix.
This will impact resources uploaded from GPX files with versions of GPXLoad prior to 0.4.0. Affected reources will need to be re-imported.
# Use and Operation:
**To Import a GPX file:**

@@ -41,3 +54,3 @@

*Note:
**Note:**

@@ -48,3 +61,45 @@ - GPXLoad preserves the uuids of resources exported from Signal K server in the GPX file, so if these GPX files are re-imported they will update the corresponding resource on the Signal K server rather than create a new resource.

- Signal K HTTP PUT api can be enabled via Signal K server *Plugin Config* screen
- GPXLoad will only accept HTTP PUT requests for one specified resource id so you will need to provide a **complete**, valid resource record as per the Signal K schema.
*Example: Add / update route*
```
HTTP PUT http://signalk-server/signalk/v1/api/vessels/self/resources/routes
{
"value":{
"urn:mrn:signalk:uuid:a8554512-5d3b-45a1-92e9-eb93da834aaa": {
"name":"KI",
"description":"KI via Edithburgh",
"distance":164006.423,
"start":"urn:mrn:signalk:uuid:e85c96e7-9bd4-4ed9-81aa-d3a350f0de55",
"end":"urn:mrn:signalk:uuid:fab5c914-b49b-4f15-a1b4-e7b90de52cb5",
"feature":{
"type":"Feature",
"geometry":{
"type":"LineString",
"coordinates":[
[137.780507,-35.781544],[137.633972,-35.557088],[137.582846,-35.551319],[137.534531,-35.589552],[137.752977,-35.08999],[138.432849,-34.885938]
]
},
"properties":{}
}
}
}
}```
- Supplying a *null* value will DELETE the resource if the configuration is set to allow delete operations.
*Example: Delete route*
```
HTTP PUT http://signalk-server/signalk/v1/api/vessels/self/resources/routes
{
"value":{
"urn:mrn:signalk:uuid:a8554512-5d3b-45a1-92e9-eb93da834aaa": null
}
}```

@@ -19,2 +19,3 @@ /*

const path= require('path')
const geoJSON = require('geojson-validation')

@@ -29,3 +30,8 @@ module.exports= function (app) {

}
let config= {}
let config= {
API: {
put: false,
delete: false
}
}

@@ -53,3 +59,18 @@ const uuidPrefix= 'urn:mrn:signalk:uuid:'

app.debug(`** ${plugin.name} started... ${(res) ? 'OK' : 'with errors!'}`)
})
})
if (app.registerActionHandler) {
app.debug('** Registering Action Handler(s) **')
app.registerActionHandler(
'vessels.self',
'resources.routes',
handlePut
)
app.registerActionHandler(
'vessels.self',
'resources.waypoints',
handlePut
)
}
}

@@ -70,5 +91,37 @@ catch (e) {

plugin.schema= { properties: { } }
plugin.schema= {
properties: {
API: {
type: "object",
description: `Use this section to allow
applications to use the Signal K HTTP PUT API to update,
replace and delete resources.`,
properties: {
put: {
type: "boolean",
title: "Enabled"
},
delete: {
type: "boolean",
title: "Enabled"
}
}
}
}
}
plugin.uiSchema= { }
plugin.uiSchema= {
API: {
put: {
"ui:widget": "checkbox",
"ui:title": "Enable / Disable PUT API",
"ui:help": "Check this box to allow resources to be added / updated via HTTP PUT api"
},
delete: {
"ui:widget": "checkbox",
"ui:title": "Allow DELETE",
"ui:help": "Check this box to allow resources to be deleted via HTTP PUT api"
}
}
}

@@ -123,6 +176,6 @@ plugin.registerWithRouter= router=> {

})
router.get(`/resources/waypoints/*-*-*-*-*`, (req, res)=> {
/*router.get(`/resources/waypoints/*-*-*-*-*`, (req, res)=> {
let fname= req.path.substring(req.path.lastIndexOf('/')+1)
res.json( getPersistedResources('waypoint', fname) )
})
})*/
router.get('/resources/routes', (req, res) => {

@@ -135,6 +188,6 @@ res.json( getPersistedResources('route').routes )

})
router.get(`/resources/routes/*-*-*-*-*`, (req, res)=> {
/*router.get(`/resources/routes/*-*-*-*-*`, (req, res)=> {
let fname= req.path.substring(req.path.lastIndexOf('/')+1)
res.json( getPersistedResources('route', fname) )
})
})*/
router.get('/resources/tracks', (req, res)=> {

@@ -147,7 +200,7 @@ res.json( getPersistedResources('track').tracks )

})
router.get(`/resources/tracks/*-*-*-*-*`, (req, res)=> {
/*router.get(`/resources/tracks/*-*-*-*-*`, (req, res)=> {
let fname= req.path.substring(req.path.lastIndexOf('/')+1)
res.json( getPersistedResources('track', fname) )
})
})*/
return router

@@ -191,29 +244,3 @@ }

// ** process posted data **
function processUIPost(data) {
app.debug(`** Loading resources.........`)
if(!Array.isArray(data)) {
app.debug(`** ERROR: ** Invalid payload data!!`)
return
}
data.forEach( r=> { persist(r) })
}
// ** save resource to file
function persist(r) {
let fname= r.id.substring(r.id.lastIndexOf(':')+1)
let p= path.join(resTypes[r.type].path, fname)
app.debug(`****** Saving ${r.type} to : ${fname} ******`)
fs.writeFile(p, JSON.stringify(r.value), (err, res)=> {
if(err) { app.debug(err) }
else { app.debug(`** ${r.type} written to ${fname} **`) }
})
if(r.type=='route') {
r.waypoints.forEach( w=> {
persist(w)
})
}
}
//** return persisted resources
//** return persisted resources from storage
function getPersistedResources(type=null, item=null) {

@@ -248,4 +275,180 @@ app.debug('*** Retrieving saved Resource(s) ***')

}
}
// ** process posted data **
function processUIPost(data) {
app.debug(`** Loading resources.........`)
if(!Array.isArray(data)) {
app.debug(`** ERROR: ** Invalid payload data!!`)
return
}
data.forEach( r=> { persist(r) })
}
// ** handle PUT via registerActionHandler
function handlePut(context, path, value, cb) {
app.debug(`
${JSON.stringify(path)},
${JSON.stringify(value)}`
)
// ** test for allowed PUT api use
if(!config.API.put) {
return {
state: 'COMPLETED',
resultStatus: 405,
message: `Method Not Allowed!`
}
}
let p= path.split('.')
if(p.length<2) {
return {
state: 'COMPLETED',
resultStatus: 400,
message: `Invalid path!`
}
}
let r={}
r.type= p[1].slice(0,p[1].length-1)
let v= Object.entries(value)
r.id= v[0][0]
r.value= v[0][1]
app.debug(r)
// ** test for allowed DELETE via PUT api
if(r.value===null && !config.API.delete) {
return {
state: 'COMPLETED',
resultStatus: 405,
message: `Method Not Allowed!`
}
}
// ** test for valid resource identifier
if( !isUUID(r.id) ) {
return {
state: 'COMPLETED',
resultStatus: 400,
message: `Invalid resource id!`
}
}
switch(r.type) {
case 'route':
case 'waypoint':
case 'track':
if(persist(r)) {
return { state: 'COMPLETED' }
}
else {
return {
state: 'COMPLETED',
resultStatus: 502,
message: `Invalid resource data values!`
}
}
break;
default:
return {
state: 'COMPLETED',
resultStatus: 400,
message: `Invalid resource type (${r.type})!`
}
}
}
// ** save / delete (r.value==null) resource file
function persist(r) {
if( !isUUID(r.id) ) { return false }
let fname= r.id.substring(r.id.lastIndexOf(':')+1)
let p= path.join(resTypes[r.type].path, fname)
let action= (r.value===null) ? 'DELETE' : 'SAVE'
app.debug(`****** ${r.type}: ${action} -> ${fname} ******`)
if(r.value===null) { // ** delete file **
fs.unlink(p, err=> {
if(err) { app.debug('Error deleting file!') }
else { app.debug('File deleted!')}
})
sendDelta(r)
}
else {
if( !validateData(r) ) { return false }
// ** test for valid SignalK value **
fs.writeFile(p, JSON.stringify(r.value), (err, res)=> {
if(err) { app.debug(err) }
else { app.debug(`** ${r.type} written to ${fname} **`) }
})
sendDelta(r)
if(r.type=='route') {
r.waypoints.forEach( w=> { persist(w) })
}
}
return true;
}
// ** send delta message for resource
function sendDelta(r) {
let key= r.id
let p= `resources.${r.type}s.${key}`
let val= [{path: p, value: r.value}]
app.debug(`****** Send Delta: ******`)
app.debug(JSON.stringify({updates: [ {values: val} ] }))
app.handleMessage(plugin.id, {updates: [ {values: val} ] })
}
// ** validate provided resource value data
function validateData(r) {
if(!r.type) { return false }
switch(r.type) {
case 'route':
return validateRoute(r.value);
break;
case 'waypoint':
return validateWaypoint(r.value);
break;
case 'track':
return validateTrack(r.value);
break;
default:
return false;
}
}
// ** validate route data
function validateRoute(r) {
if(!r.name) { return false }
if(!r.description) { return false }
if(!r.distance || isNaN(r.distance)) { return false }
if(!r.start) { return false }
if(!r.end) { return false }
if(!r.feature || !geoJSON.valid(r.feature)) {
app.debug(`****** INVALID GeoJSON ******`)
return false
}
app.debug(`****** VALID Route ******`)
return true
}
// ** validate waypoint data
function validateWaypoint(r) {
if(!r.position) { return false }
if(!r.position.latitude || !r.position.longitude) { return false }
if(!r.feature || !geoJSON.valid(r.feature)) {
app.debug(`****** INVALID GeoJSON ******`)
return false
}
app.debug(`****** VALID Waypoint ******`)
return true
}
// ** validate track data
function validateTrack(r) { return true }
// ** returns true if id is a valid UUID **
function isUUID(id) {
let uuid= RegExp("^urn:mrn:signalk:uuid:[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$")
let result= uuid.test(id)
if(!result) { app.debug(`****** INVALID ID: ${id} ******`) }
return result
}
return plugin

@@ -252,0 +455,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc