From 8d9939db0e2bf8f4d8d0b899f1f8e10c61f68308 Mon Sep 17 00:00:00 2001 From: luandro Date: Wed, 23 Oct 2024 22:16:55 -0300 Subject: [PATCH] chore: linting and do not run lint during npm publish --- .github/workflows/mapeo-migrate.yml | 5 +- public/assets/js/addLine.js | 58 ++++---- public/assets/js/api.js | 86 ++++++------ public/assets/js/mapbox-gl.js | 11 +- public/assets/js/uhttpd.service.js | 118 ++++++++--------- public/assets/js/utils.js | 198 ++++++++++++++-------------- src/api.js | 182 ++++++++++++------------- src/bin/migrate.js | 108 +++++++-------- 8 files changed, 379 insertions(+), 387 deletions(-) diff --git a/.github/workflows/mapeo-migrate.yml b/.github/workflows/mapeo-migrate.yml index 242bc00..c87ad6e 100644 --- a/.github/workflows/mapeo-migrate.yml +++ b/.github/workflows/mapeo-migrate.yml @@ -19,10 +19,7 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Install dependencies - run: npm ci - - - name: Build package - run: npm run build + run: npm install - name: Publish to npm run: npm publish diff --git a/public/assets/js/addLine.js b/public/assets/js/addLine.js index a78c54e..7ff74b4 100644 --- a/public/assets/js/addLine.js +++ b/public/assets/js/addLine.js @@ -1,31 +1,31 @@ -function addLine(map, id, point1, point2, color) { - map.addSource(id, { - 'type': 'geojson', - 'data': { - 'type': 'Feature', - 'properties': {}, - 'geometry': { - 'type': 'LineString', - 'coordinates': [ - point1, - point2 - ] - } - } - }); - map.addLayer({ - 'id': id, - 'type': 'line', - 'source': id, - 'layout': { - 'line-join': 'round', - 'line-cap': 'round' - }, - 'paint': { - 'line-color': color, - 'line-width': 4, - 'line-offset': 4 - } - }); +function addLine (map, id, point1, point2, color) { + map.addSource(id, { + type: 'geojson', + data: { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + point1, + point2 + ] + } + } + }) + map.addLayer({ + id: id, + type: 'line', + source: id, + layout: { + 'line-join': 'round', + 'line-cap': 'round' + }, + paint: { + 'line-color': color, + 'line-width': 4, + 'line-offset': 4 + } + }) } diff --git a/public/assets/js/api.js b/public/assets/js/api.js index 667a381..cf6c30b 100644 --- a/public/assets/js/api.js +++ b/public/assets/js/api.js @@ -2,71 +2,69 @@ const getCloudNodes = () => api.call('lime-utils', 'get_cloud_nodes', {}) const getMetrics = (params) => api.call('lime-metrics', 'get_metrics', params) -const getAllMetrics = (params) => params.targets.map(x => getMetrics(api, { target: x })); +const getAllMetrics = (params) => params.targets.map(x => getMetrics(api, { target: x })) -const getGateway = () => api.call('lime-metrics', 'get_gateway', {}); +const getGateway = () => api.call('lime-metrics', 'get_gateway', {}) -const getPath = (params) => api.call('lime-metrics', 'get_path', params); +const getPath = (params) => api.call('lime-metrics', 'get_path', params) -const getLastKnownPath = (params) => api.call('lime-metrics', 'get_last_internet_path', params); +const getLastKnownPath = (params) => api.call('lime-metrics', 'get_last_internet_path', params) const getMeshIfaces = (hostname) => - api.call('lime-utils', 'get_mesh_ifaces', {}, hostname) - .then(res => res.ifaces); + api.call('lime-utils', 'get_mesh_ifaces', {}, hostname) + .then(res => res.ifaces) const getAssocList = (iface, hostname) => - api.call('iwinfo', 'assoclist', { device: iface }, hostname) - .then(res => res.results); + api.call('iwinfo', 'assoclist', { device: iface }, hostname) + .then(res => res.results) // .then(res => mocked.results); -function getBatHost(mac, outgoingIface, hostname) { - return api.call('bat-hosts', 'get_bathost', { mac, outgoing_iface: outgoingIface }, hostname) - .then(response => new Promise((res, rej) => { - if (response.status === 'ok') { - res(response.bathost); - } - else { - rej(response.message); - } - })) +function getBatHost (mac, outgoingIface, hostname) { + return api.call('bat-hosts', 'get_bathost', { mac, outgoing_iface: outgoingIface }, hostname) + .then(response => new Promise((res, rej) => { + if (response.status === 'ok') { + res(response.bathost) + } else { + rej(response.message) + } + })) } -function getBoardData(hostname) { - return api.call('system', 'board', {}, hostname); +function getBoardData (hostname) { + return api.call('system', 'board', {}, hostname) } -function getSession(hostname) { - return api.call('session', 'access', {}, hostname). - then(async (result) => { - let username = null; - if (result['access-group']['root']) { - username = 'root'; - } else if (result['access-group']['lime-app']) { - username = 'lime-app'; - } - return ({ username }) - }) - .catch(async () => ({ username: null })); +function getSession (hostname) { + return api.call('session', 'access', {}, hostname) + .then(async (result) => { + let username = null + if (result['access-group'].root) { + username = 'root' + } else if (result['access-group']['lime-app']) { + username = 'lime-app' + } + return ({ username }) + }) + .catch(async () => ({ username: null })) } -function getCommunitySettings(hostname) { - return api.call('lime-utils', 'get_community_settings', {}) - +function getCommunitySettings (hostname) { + return api.call('lime-utils', 'get_community_settings', {}) } -function reboot() { - return api.call('system', 'reboot', {}).then(() => true); +function reboot () { + return api.call('system', 'reboot', {}).then(() => true) } -function checkInternet() { - return api.call('check-internet', 'is_connected', {}); +function checkInternet () { + return api.call('check-internet', 'is_connected', {}) } -async function getChangesNeedReboot() { - return sessionStorage.getItem('need-reboot') == 'yes'; +async function getChangesNeedReboot () { + return sessionStorage.getItem('need-reboot') == 'yes' } -async function setChangesNeedReboot(value) { - sessionStorage.setItem('need-reboot', value); - return value; +async function setChangesNeedReboot (value) { + sessionStorage.setItem('need-reboot', value) + return value } diff --git a/public/assets/js/mapbox-gl.js b/public/assets/js/mapbox-gl.js index c181607..a1e4497 100644 --- a/public/assets/js/mapbox-gl.js +++ b/public/assets/js/mapbox-gl.js @@ -1,9 +1,10 @@ /* Mapbox GL JS is Copyright © 2020 Mapbox and subject to the Mapbox Terms of Service ((https://www.mapbox.com/legal/tos/). */ (function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : -typeof define === 'function' && define.amd ? define(factory) : -(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mapboxgl = factory()); -}(this, (function () { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() + : typeof define === 'function' && define.amd ? define(factory) + : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mapboxgl = factory()) +}(this, function () { + 'use strict' /* eslint-disable */ @@ -40,5 +41,5 @@ var mapboxgl$1 = mapboxgl; return mapboxgl$1; -}))); +})); //# sourceMappingURL=mapbox-gl.js.map diff --git a/public/assets/js/uhttpd.service.js b/public/assets/js/uhttpd.service.js index aaa0154..17b28b9 100644 --- a/public/assets/js/uhttpd.service.js +++ b/public/assets/js/uhttpd.service.js @@ -1,70 +1,68 @@ -const UNAUTH_SESSION_ID = '00000000000000000000000000000000'; -const DEFAULT_SESSION_TIMEOUT = 5000; +const UNAUTH_SESSION_ID = '00000000000000000000000000000000' +const DEFAULT_SESSION_TIMEOUT = 5000 const parseResult = result => - new Promise((res, rej) => { - if (result.error) { return rej(result.error); } - if (result.result[0] !== 0) { return rej(result); } - result = result.result[1]; - if (result && result.status === 'error') { - return rej(result.message); - } - return res(result); - }) + new Promise((res, rej) => { + if (result.error) { return rej(result.error) } + if (result.result[0] !== 0) { return rej(result) } + result = result.result[1] + if (result && result.status === 'error') { + return rej(result.message) + } + return res(result) + }) class UhttpdService { - constructor() { - const origin = window.origin - const defaultHost = `http://thisnode.info` - this.url = `${defaultHost}/ubus`; - this.jsonrpc = '2.0'; - this.sec = 0; - this.requestList = []; - } + constructor () { + const origin = window.origin + const defaultHost = 'http://thisnode.info' + this.url = `${defaultHost}/ubus` + this.jsonrpc = '2.0' + this.sec = 0 + this.requestList = [] + } - sid() { - const sid = sessionStorage.getItem('sid'); - return sid || UNAUTH_SESSION_ID; - } + sid () { + const sid = sessionStorage.getItem('sid') + return sid || UNAUTH_SESSION_ID + } - addId() { - this.sec += 1; - return Number(this.sec); - } + addId () { + this.sec += 1 + return Number(this.sec) + } + async call (action, method, data, hostname, customSid = null, timeout = null) { + const url = hostname ? `http://${hostname}/ubus` : this.url // Must be dynamic to pull from other nodes + this.sec += 1 + const body = { + id: this.addId(), + jsonrpc: this.jsonrpc, + method: 'call', + params: [customSid || this.sid(), action, method, data] + } + const controller = new AbortController() + const id = setTimeout(() => controller.abort(), timeout || 15000) + return fetch(url, + { method: 'POST', body: JSON.stringify(body), signal: controller.signal }) + .then(response => response.json()) + .then(parseResult) + .finally(clearTimeout(id)) + } - async call(action, method, data, hostname, customSid = null, timeout = null) { - const url = hostname ? `http://${hostname}/ubus` : this.url // Must be dynamic to pull from other nodes - this.sec +=1; - const body = { - id: this.addId(), - jsonrpc: this.jsonrpc, - method: 'call', - params: [customSid || this.sid(), action, method, data] - }; - const controller = new AbortController(); - const id = setTimeout(() => controller.abort(), timeout || 15000); - return fetch(url, - { method: 'POST', body: JSON.stringify(body), signal: controller.signal }) - .then(response => response.json()) - .then(parseResult) - .finally(clearTimeout(id)); - } - - login(username, password, hostname) { - const data = { username, password, timeout: DEFAULT_SESSION_TIMEOUT }; - return this.call('session', 'login', data, hostname, UNAUTH_SESSION_ID) - .then(response => - new Promise((res, rej) => { - if (response.ubus_rpc_session) { - sessionStorage.setItem('sid', response.ubus_rpc_session); - res(response); - } - else { - rej(response); - } - })); - } + login (username, password, hostname) { + const data = { username, password, timeout: DEFAULT_SESSION_TIMEOUT } + return this.call('session', 'login', data, hostname, UNAUTH_SESSION_ID) + .then(response => + new Promise((res, rej) => { + if (response.ubus_rpc_session) { + sessionStorage.setItem('sid', response.ubus_rpc_session) + res(response) + } else { + rej(response) + } + })) + } } -const api = new UhttpdService(); \ No newline at end of file +const api = new UhttpdService() diff --git a/public/assets/js/utils.js b/public/assets/js/utils.js index 827332a..52b40f6 100644 --- a/public/assets/js/utils.js +++ b/public/assets/js/utils.js @@ -1,17 +1,17 @@ /** Generate random color */ -function getRandomColor() { - var letters = '0123456789ABCDEF'; - var color = '#'; - for (var i = 0; i < 6; i++) { - color += letters[Math.floor(Math.random() * 16)]; - } - return color; +function getRandomColor () { + const letters = '0123456789ABCDEF' + let color = '#' + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)] + } + return color } /** Get center of coords */ -function rad2degr(rad) { return rad * 180 / Math.PI; } -function degr2rad(degr) { return degr * Math.PI / 180; } +function rad2degr (rad) { return rad * 180 / Math.PI } +function degr2rad (degr) { return degr * Math.PI / 180 } /** * @param latLngInDeg array of arrays with latitude and longtitude @@ -21,117 +21,115 @@ function degr2rad(degr) { return degr * Math.PI / 180; } * @return array with the center latitude longtitude pairs in * degrees. */ -function getLatLngCenter(latLngInDegr) { - var LATIDX = 0; - var LNGIDX = 1; - var sumX = 0; - var sumY = 0; - var sumZ = 0; +function getLatLngCenter (latLngInDegr) { + const LATIDX = 0 + const LNGIDX = 1 + let sumX = 0 + let sumY = 0 + let sumZ = 0 - for (var i = 0; i < latLngInDegr.length; i++) { - var lat = degr2rad(latLngInDegr[i][LATIDX]); - var lng = degr2rad(latLngInDegr[i][LNGIDX]); - // sum of cartesian coordinates - sumX += Math.cos(lat) * Math.cos(lng); - sumY += Math.cos(lat) * Math.sin(lng); - sumZ += Math.sin(lat); - } + for (let i = 0; i < latLngInDegr.length; i++) { + var lat = degr2rad(latLngInDegr[i][LATIDX]) + var lng = degr2rad(latLngInDegr[i][LNGIDX]) + // sum of cartesian coordinates + sumX += Math.cos(lat) * Math.cos(lng) + sumY += Math.cos(lat) * Math.sin(lng) + sumZ += Math.sin(lat) + } - var avgX = sumX / latLngInDegr.length; - var avgY = sumY / latLngInDegr.length; - var avgZ = sumZ / latLngInDegr.length; + const avgX = sumX / latLngInDegr.length + const avgY = sumY / latLngInDegr.length + const avgZ = sumZ / latLngInDegr.length - // convert average x, y, z coordinate to latitude and longtitude - var lng = Math.atan2(avgY, avgX); - var hyp = Math.sqrt(avgX * avgX + avgY * avgY); - var lat = Math.atan2(avgZ, hyp); + // convert average x, y, z coordinate to latitude and longtitude + var lng = Math.atan2(avgY, avgX) + const hyp = Math.sqrt(avgX * avgX + avgY * avgY) + var lat = Math.atan2(avgZ, hyp) - return ([rad2degr(lat), rad2degr(lng)]); + return ([rad2degr(lat), rad2degr(lng)]) } /** Slugify */ -function slugify(text) { - return text.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, ''); // Trim - from end of text +function slugify (text) { + return text.toString().toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(/[^\w\-]+/g, '') // Remove all non-word chars + .replace(/\-\-+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text } /** un-link observation from hostname */ -function unlinkObservation(observationId, observationVersion) { - axios.put('/mapeo', { - observationId, - observationVersion, - nodeHostname: null, - nodeModel: 'router' // +function unlinkObservation (observationId, observationVersion) { + axios.put('/mapeo', { + observationId, + observationVersion, + nodeHostname: null, + nodeModel: 'router' // + }) + .then(update => { + observationsToMarkers({ noFly: true, filter: true }) }) - .then(update => { - observationsToMarkers({ noFly: true, filter: true }) - }) - .catch(err => console.log(err)) + .catch(err => console.log(err)) } /** update observation with libremesh node information */ -function updateObservation(node, observationId, observationVersion) { - api.login('lime-app', 'generic', node) - .then(() => { - getBoardData(node) - .then(data => { - axios.put('/mapeo', { - observationId, - observationVersion, - nodeHostname: node, - nodeModel: slugify(data.model) - }) - .then(update => { - observationsToMarkers({ noFly: true, filter: true }) - }) - .catch(err => console.log(err)) - }) - .catch(err => console.log(err)) +function updateObservation (node, observationId, observationVersion) { + api.login('lime-app', 'generic', node) + .then(() => { + getBoardData(node) + .then(data => { + axios.put('/mapeo', { + observationId, + observationVersion, + nodeHostname: node, + nodeModel: slugify(data.model) + }) + .then(update => { + observationsToMarkers({ noFly: true, filter: true }) + }) + .catch(err => console.log(err)) }) - .catch(err => console.log('Auth error', err)) + .catch(err => console.log(err)) + }) + .catch(err => console.log('Auth error', err)) } /** delete observation */ -async function deleteObservation(observationId) { - let deleteButton = document.getElementById(`delete-button-${observationId}`) - deleteButton.classList.add = 'hidden' - const update = await axios.delete('/mapeo', { data: { observationId } }) - await observationsToMarkers({ noFly: true, filter: true }) - deleteButton.classList.remove = 'hidden' +async function deleteObservation (observationId) { + const deleteButton = document.getElementById(`delete-button-${observationId}`) + deleteButton.classList.add = 'hidden' + const update = await axios.delete('/mapeo', { data: { observationId } }) + await observationsToMarkers({ noFly: true, filter: true }) + deleteButton.classList.remove = 'hidden' } /** check is in filter */ -function checkIsFiltered(obs, filter) { - if (filter) return obs.tags?.type === 'network' - else return obs +function checkIsFiltered (obs, filter) { + if (filter) return obs.tags?.type === 'network' + else return obs } -async function observationsToMarkers({ noFly, filter }) { - const map = window.mapboxMap - const session = await getSession() - if (!session?.username) await api.login('lime-app', 'generic') - try { - // Get local storage - const localObs = window.localStorage.getItem('mapeo-obs') - const localNodes = window.localStorage.getItem('lime-nodes') - const parsedObs = JSON.parse(localObs) - const parsedNodes = JSON.parse(localNodes) - if (parsedObs && parsedNodes) await generateHtml(parsedObs, parsedNodes) - const getMapeoData = await axios.get('/mapeo') - const mapeoData = getMapeoData.data - const cloudNodesData = await getCloudNodes() - const cloudNodes = cloudNodesData.nodes - // Set local storage - window.localStorage.setItem('mapeo-obs', JSON.stringify(mapeoData)) - window.localStorage.setItem('lime-nodes', JSON.stringify(cloudNodes)) - /** generate the html */ - await generateHtml(mapeoData, cloudNodes, noFly, filter) - } catch (err) { - console.log('Error', err) - } +async function observationsToMarkers ({ noFly, filter }) { + const map = window.mapboxMap + const session = await getSession() + if (!session?.username) await api.login('lime-app', 'generic') + try { + // Get local storage + const localObs = window.localStorage.getItem('mapeo-obs') + const localNodes = window.localStorage.getItem('lime-nodes') + const parsedObs = JSON.parse(localObs) + const parsedNodes = JSON.parse(localNodes) + if (parsedObs && parsedNodes) await generateHtml(parsedObs, parsedNodes) + const getMapeoData = await axios.get('/mapeo') + const mapeoData = getMapeoData.data + const cloudNodesData = await getCloudNodes() + const cloudNodes = cloudNodesData.nodes + // Set local storage + window.localStorage.setItem('mapeo-obs', JSON.stringify(mapeoData)) + window.localStorage.setItem('lime-nodes', JSON.stringify(cloudNodes)) + /** generate the html */ + await generateHtml(mapeoData, cloudNodes, noFly, filter) + } catch (err) { + console.log('Error', err) + } } - - diff --git a/src/api.js b/src/api.js index 3fda10b..c19866c 100644 --- a/src/api.js +++ b/src/api.js @@ -2,102 +2,102 @@ const path = require('path') const fastify = require('fastify')({ logger: true }) module.exports = (mapeo, filteredType) => { - fastify.get('/', (req, reply) => { - reply.sendFile('index.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly - }) - fastify.get('/mapeo', (req, reply) => { - const { category, name } = req.query - mapeo.observationList(null, (err, data) => { - if (err) { - console.error(err) - return reply.status(500).send({ error: 'Internal Server Error' }) - } - let filteredData = data - if (category) { - const categories = Array.isArray(category) ? category : [category] - filteredData = filteredData.filter(obs => { - return obs.tags && obs.tags.categoryId && categories.includes(obs.tags.categoryId) - }) - } - if (name) { - const lowercaseName = name.toLowerCase(); - filteredData = filteredData.filter(obs => { - return obs.tags && obs.tags.name && obs.tags.name.toLowerCase().includes(lowercaseName); - }); - } - reply.send(filteredData); + fastify.get('/', (req, reply) => { + reply.sendFile('index.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly + }) + fastify.get('/mapeo', (req, reply) => { + const { category, name } = req.query + mapeo.observationList(null, (err, data) => { + if (err) { + console.error(err) + return reply.status(500).send({ error: 'Internal Server Error' }) + } + let filteredData = data + if (category) { + const categories = Array.isArray(category) ? category : [category] + filteredData = filteredData.filter(obs => { + return obs.tags && obs.tags.categoryId && categories.includes(obs.tags.categoryId) }) - }) - fastify.post('/mapeo', (req, reply) => { - const { lat, lng } = req.body - const obs = { - attachments: [], - type: 'observation', - lat, - lon: lng, - tags: { - categoryId: 'router', - type: 'network' - } - } - mapeo.observationCreate(obs, (err, data) => { - if (err) console.error(err) - reply.send(data) + } + if (name) { + const lowercaseName = name.toLowerCase() + filteredData = filteredData.filter(obs => { + return obs.tags && obs.tags.name && obs.tags.name.toLowerCase().includes(lowercaseName) }) + } + reply.send(filteredData) }) - fastify.put('/mapeo', async (req, reply) => { - try { - const { observationId, observationVersion, nodeHostname, nodeModel } = req.body - const obs = { - version: observationVersion, - id: observationId, - type: 'observation', - tags: { - categoryId: nodeModel, - hostname: nodeHostname, - type: 'network' - } - } - console.log('Updating observation:', obs) - const data = await new Promise((resolve, reject) => { - mapeo.observationUpdate(obs, (err, result) => { - if (err) reject(err) - else resolve(result) - }) - }) - console.log('Update successful:', data) - reply.send(data) - } catch (error) { - console.error('Error updating observation:', error) - reply.status(500).send({ error: 'Internal Server Error' }) - } + }) + fastify.post('/mapeo', (req, reply) => { + const { lat, lng } = req.body + const obs = { + attachments: [], + type: 'observation', + lat, + lon: lng, + tags: { + categoryId: 'router', + type: 'network' + } + } + mapeo.observationCreate(obs, (err, data) => { + if (err) console.error(err) + reply.send(data) }) - fastify.delete('/mapeo', (req, reply) => { - console.log('req.body', req.body) - const { observationId } = req.body - mapeo.observationDelete(observationId, (err, data) => { - console.log('data', data) - if (err) { - console.error(err) - reply.err(err) - } - reply.send(data) + }) + fastify.put('/mapeo', async (req, reply) => { + try { + const { observationId, observationVersion, nodeHostname, nodeModel } = req.body + const obs = { + version: observationVersion, + id: observationId, + type: 'observation', + tags: { + categoryId: nodeModel, + hostname: nodeHostname, + type: 'network' + } + } + console.log('Updating observation:', obs) + const data = await new Promise((resolve, reject) => { + mapeo.observationUpdate(obs, (err, result) => { + if (err) reject(err) + else resolve(result) }) + }) + console.log('Update successful:', data) + reply.send(data) + } catch (error) { + console.error('Error updating observation:', error) + reply.status(500).send({ error: 'Internal Server Error' }) + } + }) + fastify.delete('/mapeo', (req, reply) => { + console.log('req.body', req.body) + const { observationId } = req.body + mapeo.observationDelete(observationId, (err, data) => { + console.log('data', data) + if (err) { + console.error(err) + reply.err(err) + } + reply.send(data) }) + }) - // Run the server! - const start = async () => { - await fastify.register(require('@fastify/cors')) - await fastify.register(require('@fastify/static'), { - root: path.join(__dirname, '..', 'public'), - prefix: '/', // optional: default '/' - }) - try { - await fastify.listen({ host: '0.0.0.0', port: 3000 }) - } catch (err) { - fastify.log.error(err) - process.exit(1) - } + // Run the server! + const start = async () => { + await fastify.register(require('@fastify/cors')) + await fastify.register(require('@fastify/static'), { + root: path.join(__dirname, '..', 'public'), + prefix: '/' // optional: default '/' + }) + try { + await fastify.listen({ host: '0.0.0.0', port: 3000 }) + } catch (err) { + fastify.log.error(err) + process.exit(1) } - start() -} \ No newline at end of file + } + start() +} diff --git a/src/bin/migrate.js b/src/bin/migrate.js index eac3fcb..af35d04 100755 --- a/src/bin/migrate.js +++ b/src/bin/migrate.js @@ -1,8 +1,8 @@ #!/usr/bin/env node -const fetch = require('node-fetch'); -const Mapeo = require('../mapeo'); -const { Command } = require('commander'); +const fetch = require('node-fetch') +const Mapeo = require('../mapeo') +const { Command } = require('commander') /** * Updates the category IDs of observations based on the provided categories. @@ -18,30 +18,30 @@ const { Command } = require('commander'); * Logs the result of each update attempt, a summary of changes, and a message upon completion, * or logs an error if any occurs during the process. */ -async function updateCategories(categoriesToFetch, newCategory, isDryRun) { - console.log('Starting migration process...'); - const changes = []; +async function updateCategories (categoriesToFetch, newCategory, isDryRun) { + console.log('Starting migration process...') + const changes = [] try { - console.log(`Fetching observations for categories: ${categoriesToFetch.join(', ')}`); + console.log(`Fetching observations for categories: ${categoriesToFetch.join(', ')}`) // Fetch observations for specified categories - const queryParams = new URLSearchParams(categoriesToFetch.map(cat => ['category', cat])); - const response = await fetch(`http://localhost:3000/mapeo?${queryParams}`); + const queryParams = new URLSearchParams(categoriesToFetch.map(cat => ['category', cat])) + const response = await fetch(`http://localhost:3000/mapeo?${queryParams}`) - const observations = await response.json(); + const observations = await response.json() - console.log(`Fetched ${observations.length} observations.`); + console.log(`Fetched ${observations.length} observations.`) // Update observations for (const observation of observations) { - const currentCategoryId = observation.tags.categoryId; + const currentCategoryId = observation.tags.categoryId // Only process observations within the specified categories if (categoriesToFetch.includes(currentCategoryId)) { - console.log(`Processing observation ${observation.id} with current category: ${currentCategoryId}`); + console.log(`Processing observation ${observation.id} with current category: ${currentCategoryId}`) - console.log(`Updating category for observation ${observation.id}: ${currentCategoryId} -> ${newCategory}`); + console.log(`Updating category for observation ${observation.id}: ${currentCategoryId} -> ${newCategory}`) // Prepare the update payload const updatePayload = { @@ -49,12 +49,12 @@ async function updateCategories(categoriesToFetch, newCategory, isDryRun) { observationVersion: observation.version, nodeHostname: observation.tags.hostname || '', nodeModel: newCategory - }; + } if (!isDryRun) { - let updateSuccessful = false; - let retries = 0; - const maxRetries = 3; + let updateSuccessful = false + let retries = 0 + const maxRetries = 3 while (!updateSuccessful && retries < maxRetries) { try { @@ -62,45 +62,45 @@ async function updateCategories(categoriesToFetch, newCategory, isDryRun) { const updateResponse = await fetch('http://localhost:3000/mapeo', { method: 'PUT', headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json' }, - body: JSON.stringify(updatePayload), - }); + body: JSON.stringify(updatePayload) + }) if (updateResponse.ok) { - console.log(`Successfully updated observation ${observation.id}`); - updateSuccessful = true; + console.log(`Successfully updated observation ${observation.id}`) + updateSuccessful = true } else { - throw new Error(`Failed to update observation ${observation.id}`); + throw new Error(`Failed to update observation ${observation.id}`) } } catch (error) { - console.error(`Attempt ${retries + 1} failed: ${error.message}`); - retries++; + console.error(`Attempt ${retries + 1} failed: ${error.message}`) + retries++ if (retries < maxRetries) { - console.log(`Retrying update for observation ${observation.id}...`); + console.log(`Retrying update for observation ${observation.id}...`) } else { - throw new Error(`Max retries reached for observation ${observation.id}. Moving to next observation.`); + throw new Error(`Max retries reached for observation ${observation.id}. Moving to next observation.`) } } } } else { - console.log(`Dry run: Would update observation ${observation.id}`); + console.log(`Dry run: Would update observation ${observation.id}`) } - changes.push({ id: observation.id, from: currentCategoryId, to: newCategory }); + changes.push({ id: observation.id, from: currentCategoryId, to: newCategory }) } else { - console.log(`Skipping observation ${observation.id} with category: ${currentCategoryId} (not in target categories)`); + console.log(`Skipping observation ${observation.id} with category: ${currentCategoryId} (not in target categories)`) } } - console.log(isDryRun ? 'Dry run completed' : 'Migration completed'); - console.log('Summary of changes:'); - console.table(changes); + console.log(isDryRun ? 'Dry run completed' : 'Migration completed') + console.log('Summary of changes:') + console.table(changes) } catch (error) { - console.error('Error during migration:', error); + console.error('Error during migration:', error) } } -const program = new Command(); +const program = new Command() program .name('mapeo-migrate') @@ -114,36 +114,36 @@ program Example: $ mapeo-migrate --from category1,category2 --to newCategory --key yourProjectKey $ mapeo-migrate -f category1,category2 -t newCategory -k yourProjectKey --dry-run`) - .parse(process.argv); + .parse(process.argv) -const options = program.opts(); +const options = program.opts() -const projectKey = options.key || process.env.MAPEO_PROJECT_KEY; +const projectKey = options.key || process.env.MAPEO_PROJECT_KEY if (!projectKey) { - console.error('Error: Project key must be provided either as --key option or MAPEO_PROJECT_KEY environment variable'); - process.exit(1); + console.error('Error: Project key must be provided either as --key option or MAPEO_PROJECT_KEY environment variable') + process.exit(1) } (async () => { try { - const categoriesToFetch = options.from.split(',').map(cat => cat.trim()); - const newCategory = options.to; - const isDryRun = options.dryRun || false; + const categoriesToFetch = options.from.split(',').map(cat => cat.trim()) + const newCategory = options.to + const isDryRun = options.dryRun || false - console.log('Categories to fetch:', categoriesToFetch); - console.log('New category:', newCategory); - if (isDryRun) console.log('Dry run mode: No actual updates will be made'); + console.log('Categories to fetch:', categoriesToFetch) + console.log('New category:', newCategory) + if (isDryRun) console.log('Dry run mode: No actual updates will be made') - const mapeoInstance = new Mapeo({}); - mapeoInstance.get(projectKey); + const mapeoInstance = new Mapeo({}) + mapeoInstance.get(projectKey) // Wait for 5 seconds to allow the API to start - await new Promise(resolve => setTimeout(resolve, 5000)); + await new Promise(resolve => setTimeout(resolve, 5000)) - await updateCategories(categoriesToFetch, newCategory, isDryRun, mapeoInstance); + await updateCategories(categoriesToFetch, newCategory, isDryRun, mapeoInstance) } catch (error) { - console.error('Error:', error.message); - process.exit(1); + console.error('Error:', error.message) + process.exit(1) } -})(); +})()