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

@fboes/aerofly-patterns

Package Overview
Dependencies
Maintainers
0
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fboes/aerofly-patterns - npm Package Compare versions

Comparing version 2.3.6 to 2.3.7

5

CHANGELOG.md
# Changelog
# 2.3.7
- Updated mission file generator, adding tags
- Added Data Transfer Objects for Aviation Weather API
## 2.3.6

@@ -4,0 +9,0 @@

3

dist/index.test.js
// @ts-check
import { AirportTest } from "./lib/Airport.test.js";
import { AviationWeatherApiTest, AviationWeatherApiHelpersTest } from "./lib/AviationWeatherApi.test.js";
import { AviationWeatherApiTest } from "./lib/AviationWeatherApi.test.js";
import { DateYielderTest } from "./lib/DateYielder.test.js";

@@ -10,3 +10,2 @@ import { DegreeTest } from "./lib/Degree.test.js";

new AviationWeatherApiTest();
new AviationWeatherApiHelpersTest();
new DateYielderTest();

@@ -13,0 +12,0 @@ new DegreeTest();

@@ -191,2 +191,3 @@ // @ts-check

description: s.description ?? "",
tags: s.tags,
flightSetting: "cruise",

@@ -312,3 +313,3 @@ aircraft: {

? pad("Calm", 13)
: `${pad(s.weather?.windDirection, 3, true)}° @ ${pad(s.weather?.windSpeed, 2, true)} kts`,
: `${pad(s.weather?.windDirection, 3, true)}° @ ${pad(s.weather?.windSpeed, 2, true)} kts`,
clouds,

@@ -315,0 +316,0 @@ pad(Math.round(s.weather?.visibility ?? 0), 7, true) + " SM",

@@ -8,3 +8,3 @@ // @ts-check

import { Formatter } from "./Formatter.js";
import { AviationWeatherApiHelpers } from "./AviationWeatherApi.js";
import { AviationWeatherNormalizedAirport } from "./AviationWeatherApi.js";

@@ -17,23 +17,15 @@ /**

*
* @param {import('./AviationWeatherApi.js').AviationWeatherApiAirport} airportJson
* @param {import('./AviationWeatherApi.js').AviationWeatherApiAirport} airportApiData
* @param {import('./Configuration.js').Configuration?} configuration
*/
constructor(airportJson, configuration = null) {
this.id = airportJson.icaoId;
this.position = new Point(airportJson.lon, airportJson.lat, airportJson.elev);
constructor(airportApiData, configuration = null) {
const airportNormalized = new AviationWeatherNormalizedAirport(airportApiData);
this.id = airportNormalized.icaoId;
this.position = new Point(airportNormalized.lon, airportNormalized.lat, airportNormalized.elev);
/**
* @type {string}
*/
this.name = airportJson.name
.replace(/_/g, " ")
.trim()
.replace(/\bINTL\b/g, "INTERNATIONAL")
.replace(/\bRGNL\b/g, "REGIONAL")
.replace(/\bFLD\b/g, "FIELD")
.replace(/(\/)/g, " $1 ")
.toLowerCase()
.replace(/(^|\s)[a-z]/g, (char) => {
return char.toUpperCase();
});
this.name = airportNormalized.name;

@@ -50,3 +42,3 @@ // Remove municipality name if already present in airport name

this.runways = [];
airportJson.runways.map((r) => {
airportNormalized.runways.map((r) => {
this.buildRunways(r, this.position, configuration).forEach((runway) => {

@@ -80,10 +72,3 @@ runway && this.runways.push(runway);

*/
this.magneticDeclination = 0;
const magdecMatch = airportJson.magdec.match(/^(\d+)(E|W)$/);
if (magdecMatch) {
this.magneticDeclination = Number(magdecMatch[1]);
if (magdecMatch[2] === "W") {
this.magneticDeclination *= -1;
}
}
this.magneticDeclination = airportNormalized.magdec;

@@ -99,3 +84,3 @@ /**

*/
this.hasTower = airportJson.tower === "T";
this.hasTower = airportNormalized.tower;

@@ -105,5 +90,5 @@ /**

*/
this.hasBeacon = airportJson.beacon === "B";
this.hasBeacon = airportNormalized.beacon;
const lclP = AviationWeatherApiHelpers.fixFrequencies(airportJson.freqs).find((f) => {
const lclP = airportNormalized.freqs.find((f) => {
return f.type === "LCL/P";

@@ -187,3 +172,3 @@ });

*
* @param {import('./AviationWeatherApi.js').AviationWeatherApiRunway} runwayJson
* @param {import('./AviationWeatherApi.js').AviationWeatherNormalizedRunway} runwayApiData
* @param {Point} airportPosition

@@ -193,10 +178,7 @@ * @param {import('./Configuration.js').Configuration?} configuration

*/
buildRunways(runwayJson, airportPosition, configuration) {
buildRunways(runwayApiData, airportPosition, configuration) {
/**
* @type {[string,string]} both directions
*/
const id = ["", ""];
runwayJson.id.split("/").forEach((i, index) => {
id[index] = i;
});
const id = runwayApiData.id;

@@ -206,16 +188,10 @@ /**

*/
const dimension = [0, 0];
runwayJson.dimension
.split("x")
.map((x) => Number(x))
.forEach((d, index) => {
dimension[index] = d;
});
const dimension = runwayApiData.dimension;
// Helipads & Water runways get an approximate alignment
if (runwayJson.alignment === "-") {
runwayJson.alignment = id[0].replace(/\D/g, "") + "0";
if (runwayApiData.alignment === null) {
runwayApiData.alignment = Number(id[0].replace(/\D/g, "") + "0");
}
const alignmentBase = Number(runwayJson.alignment);
const alignmentBase = runwayApiData.alignment;
if (isNaN(alignmentBase)) {

@@ -222,0 +198,0 @@ return [];

@@ -23,3 +23,3 @@ //@ts-check

magdec: "02E",
rwyNum: 3,
rwyNum: "3",
tower: "T",

@@ -84,3 +84,3 @@ beacon: "B",

magdec: "15W",
rwyNum: 2,
rwyNum: "2",
tower: "T",

@@ -130,3 +130,3 @@ beacon: "B",

magdec: "14E",
rwyNum: 3,
rwyNum: "3",
tower: "T",

@@ -133,0 +133,0 @@ beacon: "B",

// @ts-check
import { Vector } from "@fboes/geojson";
import { Point } from "@fboes/geojson";
import { Vector, Point } from "@fboes/geojson";
/**
* @typedef {object} AviationWeatherApiCloud
* @property {"CAVOK"|"CLR"|"FEW"|"SCT"|"BKN"|"OVC"} cover with {CLR: 0, FEW: 1/8, SCT: 2/8, BKN: 4/8, OVC: 1}
* @property {"CAVOK"|"CLR"|"SKC"|"FEW"|"SCT"|"BKN"|"OVC"} cover with {CLR: 0, FEW: 1/8, SCT: 2/8, BKN: 4/8, OVC: 1}
* @property {number?} base 1900 ft AGL

@@ -45,3 +44,3 @@ * @see https://aviationweather.gov/data/api/#/Data/dataMetar

/**
* @typedef {object} AviationWeatherApiFrequencies
* @typedef {object} AviationWeatherApiFrequency
* @property {string} type "LCL/P" or "-"

@@ -60,7 +59,7 @@ * @property {number} [freq] 121.4

* @property {string} magdec "02E" for East, "--" obiously for true headings
* @property {number} rwyNum
* @property {string} rwyNum
* @property {"T"|"-"|null} tower
* @property {"B"|"-"|null} beacon
* @property {AviationWeatherApiRunway[]} runways
* @property {AviationWeatherApiFrequencies[]|string} freqs or "LCL/P,123.9;ATIS,124.7"
* @property {AviationWeatherApiFrequency[]|string} freqs or "LCL/P,123.9;ATIS,124.7"
* @see https://aviationweather.gov/data/api/#/Data/dataAirport

@@ -97,3 +96,3 @@ */

// hours,
// bbox: AviationWeatherApiHelpers.buildBbox(position, distance).join(","),
// bbox: AviationWeatherApi.buildBbox(position, distance).join(","),
date: date ? date.toISOString().replace(/\.\d+(Z)/, "$1") : "",

@@ -114,3 +113,3 @@ }),

ids: ids.join(","),
// bbox: AviationWeatherApiHelpers.buildBbox(position, distance).join(","),
// bbox: AviationWeatherApi.buildBbox(position, distance).join(","),
format: "json",

@@ -133,3 +132,3 @@ }),

format: "json",
bbox: AviationWeatherApiHelpers.buildBbox(position, distance).join(","),
bbox: AviationWeatherApi.buildBbox(position, distance).join(","),
}),

@@ -155,33 +154,5 @@ );

}
}
export class AviationWeatherApiHelpers {
/**
*
* @param {AviationWeatherApiFrequencies[]|string} freq
* @returns {AviationWeatherApiFrequencies[]}
*/
static fixFrequencies(freq) {
if (typeof freq !== "string") {
return freq;
}
return freq.split(";").map(
/**
*
* @param {string} f
* @returns {AviationWeatherApiFrequencies}
*/
(f) => {
const parts = f.split(",");
return {
type: parts[0],
freq: parts[1] ? Number(parts[1]) : undefined,
};
},
);
}
/**
*
* @param {Point} position

@@ -197,1 +168,244 @@ * @param {number} [distance] in meters

}
export class AviationWeatherNormalizedAirport {
/**
* @param {AviationWeatherApiAirport} apiData
*/
constructor({ icaoId, name, type, lat, lon, elev, magdec, rwyNum, tower, beacon, runways, freqs }) {
/**
* @type {string}
*/
this.icaoId = icaoId;
/**
* @type {string}
*/
this.name = name
.replace(/_/g, " ")
.trim()
.replace(/\bINTL\b/g, "INTERNATIONAL")
.replace(/\bRGNL\b/g, "REGIONAL")
.replace(/\bFLD\b/g, "FIELD")
.replace(/(\/)/g, " $1 ")
.toLowerCase()
.replace(/(^|\s)[a-z]/g, (char) => {
return char.toUpperCase();
});
/**
* @type {"ARP"|"HEL"}
*/
this.type = type;
/**
* @type {number}
*/
this.lat = lat;
/**
* @type {number}
*/
this.lon = lon;
/**
* @type {number} in meters MSL
*/
this.elev = elev;
/**
* @type {number} with "+" to the east and "-" to the west. Substracted to a true heading this will give the magnetic heading.
*/
this.magdec = 0;
const magdecMatch = magdec.match(/^(\d+)(E|W)$/);
if (magdecMatch) {
this.magdec = Number(magdecMatch[1]);
if (magdecMatch[2] === "W") {
this.magdec *= -1;
}
}
/**
* @type {number}
*/
this.rwyNum = Number(rwyNum);
/**
* @type {boolean}
*/
this.tower = tower === "T";
/**
* @type {boolean}
*/
this.beacon = beacon === "B";
/**
* @type {AviationWeatherNormalizedRunway[]}
*/
this.runways = runways.map((r) => {
return new AviationWeatherNormalizedRunway(r);
});
/**
* @type {AviationWeatherApiFrequency[]}
*/
this.freqs =
typeof freqs !== "string"
? freqs
: freqs.split(";").map(
/**
* @param {string} f
* @returns {AviationWeatherApiFrequency}
*/
(f) => {
const parts = f.split(",");
return {
type: parts[0],
freq: parts[1] ? Number(parts[1]) : undefined,
};
},
);
}
}
export class AviationWeatherNormalizedRunway {
/**
*
* @param {AviationWeatherApiRunway} apiData
*/
constructor({ id, dimension, surface, alignment }) {
/**
* @type {[string,string]} both directions
*/
this.id = ["", ""];
id.split("/").forEach((i, index) => {
this.id[index] = i;
});
/**
* @type {[number,number]} length, width in ft
*/
this.dimension = [0, 0];
dimension
.split("x")
.map((x) => Number(x))
.forEach((d, index) => {
this.dimension[index] = d;
});
/**
* @type {AviationWeatherApiRunwaySurface}
*/
this.surface = surface;
/**
* @type {number?}
*/
this.alignment = alignment !== "-" ? Number(alignment) : null;
}
}
export class AviationWeatherNormalizedMetar {
/**
*
* @param {AviationWeatherApiMetar} apiData
*/
constructor({ icaoId, reportTime, temp, dewp, wdir, wspd, wgst, visib, altim, lat, lon, elev, clouds }) {
/**
* @type {string}
*/
this.icaoId = icaoId;
/**
* @type {Date}
*/
this.reportTime = new Date(Date.parse(reportTime + " GMT"));
/**
* @type {number} in °C
*/
this.temp = temp;
/**
* @type {number} in °C
*/
this.dewp = dewp;
/**
* @type {number?} in °, null on VRB
*/
this.wdir = wdir !== "VRB" ? wdir : null;
/**
* @type {number} in kts
*/
this.wspd = wspd;
/**
* @type {number?} in kts
*/
this.wgst = wgst;
/**
* @type {number} in SM, 99 on any distance being open-ended
*/
this.visib = typeof visib === "string" ? 99 : visib;
/**
* @type {number} in hPa
*/
this.altim = altim;
/**
* @type {number}
*/
this.lat = lat;
/**
* @type {number}
*/
this.lon = lon;
/**
* @type {number} meters MSL
*/
this.elev = elev;
/**
* @type {AviationWeatherNormalizedCloud[]}
*/
this.clouds = clouds.map((c) => {
return new AviationWeatherNormalizedCloud(c);
});
}
}
export class AviationWeatherNormalizedCloud {
/**
* @param {AviationWeatherApiCloud} apiData
*/
constructor({ cover, base }) {
/**
* @type {"CLR"|"FEW"|"SCT"|"BKN"|"OVC"}
*/
this.cover = cover === "CAVOK" || cover === "SKC" ? "CLR" : cover;
const coverOctas = {
CLR: 0,
FEW: 1,
SCT: 2,
BKN: 4,
OVC: 8,
};
/**
* @type {number} 0..8
*/
this.coverOctas = coverOctas[this.cover] ?? 0;
/**
* @type {number?} in feet AGL
*/
this.base = base;
}
}
// @ts-check
import { strict as assert } from "node:assert";
import { AviationWeatherApi, AviationWeatherApiHelpers } from "./AviationWeatherApi.js";
import { AviationWeatherApi, AviationWeatherNormalizedAirport } from "./AviationWeatherApi.js";

@@ -21,15 +21,30 @@ export class AviationWeatherApiTest {

airports.forEach((airport) => {
assert.ok(airport.icaoId, "airport.icaoId");
assert.strictEqual(typeof airport.icaoId, "string", "airport.icaoId");
assert.ok(icaoCodes.indexOf(airport.icaoId) > -1);
assert.ok(airport.name, "airport.name");
assert.ok(airport.type, "airport.type");
assert.ok(airport.lat, "airport.lat");
assert.ok(airport.lon, "airport.lon");
assert.ok(airport.elev, "airport.elev");
assert.ok(airport.magdec, "airport.magdec");
assert.ok(airport.rwyNum, "airport.rwyNum");
assert.ok(airport.tower, "airport.tower");
assert.ok(airport.beacon, "airport.beacon");
assert.strictEqual(typeof airport.name, "string", "airport.name");
assert.strictEqual(typeof airport.type, "string", "airport.type");
assert.strictEqual(typeof airport.lat, "number", "airport.lat");
assert.strictEqual(typeof airport.lon, "number", "airport.lon");
assert.strictEqual(typeof airport.elev, "number", "airport.elev");
assert.strictEqual(typeof airport.magdec, "string", "airport.magdec");
assert.strictEqual(typeof airport.rwyNum, "string", "airport.rwyNum");
assert.strictEqual(typeof airport.tower, "string", "airport.tower");
assert.strictEqual(typeof airport.beacon, "string", "airport.beacon");
assert.ok(Array.isArray(airport.runways), "airport.runways");
assert.ok(Array.isArray(airport.freqs) || typeof airport.freqs === "string", "airport.freqs");
const airportNormalized = new AviationWeatherNormalizedAirport(airport);
assert.strictEqual(typeof airportNormalized.icaoId, "string", "airportNormalized.icaoId");
assert.ok(icaoCodes.indexOf(airportNormalized.icaoId) > -1);
assert.strictEqual(typeof airportNormalized.name, "string", "airportNormalized.name");
assert.strictEqual(typeof airportNormalized.type, "string", "airportNormalized.type");
assert.strictEqual(typeof airportNormalized.lat, "number", "airportNormalized.lat");
assert.strictEqual(typeof airportNormalized.lon, "number", "airportNormalized.lon");
assert.strictEqual(typeof airportNormalized.elev, "number", "airportNormalized.elev");
assert.strictEqual(typeof airportNormalized.magdec, "number", "airportNormalized.magdec");
assert.strictEqual(typeof airportNormalized.rwyNum, "number", "airportNormalized.rwyNum");
assert.strictEqual(typeof airportNormalized.tower, "boolean", "airportNormalized.tower");
assert.strictEqual(typeof airportNormalized.beacon, "boolean", "airportNormalized.beacon");
assert.ok(Array.isArray(airportNormalized.runways), "airportNormalized.runways");
assert.ok(Array.isArray(airportNormalized.freqs), "airportNormalized.freqs");
});

@@ -45,41 +60,10 @@

metars.forEach((metar) => {
assert.strictEqual(typeof metar.lat, "number", "metar.lat");
assert.strictEqual(typeof metar.lon, "number", "metar.lon");
assert.strictEqual(typeof metar.elev, "number", "metar.elev");
});
console.log(`✅ ${this.constructor.name}.fetchMetar successful`);
}
}
export class AviationWeatherApiHelpersTest {
constructor() {
this.fixFrequencies();
}
fixFrequencies() {
{
const expected = AviationWeatherApiHelpers.fixFrequencies("LCL/P,123.9;ATIS,124.7");
assert.strictEqual(expected.length, 2);
assert.strictEqual(expected[0].type, "LCL/P");
assert.strictEqual(expected[0].freq, 123.9);
}
{
const expected = AviationWeatherApiHelpers.fixFrequencies("-");
assert.strictEqual(expected.length, 1);
assert.strictEqual(expected[0].type, "-");
assert.strictEqual(expected[0].freq, undefined);
}
{
const expected = AviationWeatherApiHelpers.fixFrequencies([
{ type: "LCL/P", freq: 123.9 },
{ type: "ATIS", freq: 124.7 },
]);
assert.strictEqual(expected.length, 2);
assert.strictEqual(expected[0].type, "LCL/P");
assert.strictEqual(expected[0].freq, 123.9);
}
console.log(`✅ ${this.constructor.name}.fixFrequencies successful`);
}
}

@@ -6,2 +6,3 @@ //@ts-check

import { ScenarioWeather, ScenarioWeatherCloud } from "./Scenario.js";
import { AviationWeatherNormalizedCloud } from "./AviationWeatherApi.js";

@@ -77,3 +78,3 @@ export class FormatterTest {

w.clouds[0] = new ScenarioWeatherCloud("OVC", 1000);
w.clouds[0] = new ScenarioWeatherCloud(new AviationWeatherNormalizedCloud({ cover: "OVC", base: 1000 }));
assert.strictEqual("foggy", Formatter.getWeatherAdjectives(w));

@@ -80,0 +81,0 @@

@@ -6,3 +6,3 @@ // @ts-check

import { Configuration } from "./Configuration.js";
import { AviationWeatherApi } from "./AviationWeatherApi.js";
import { AviationWeatherApi, AviationWeatherNormalizedMetar } from "./AviationWeatherApi.js";
import { Formatter } from "./Formatter.js";

@@ -226,2 +226,29 @@ import { AeroflyAircraftFinder } from "../data/AeroflyAircraft.js";

/**
* @returns {string[]}
*/
get tags() {
const tags = ["approach", "pattern", "practice"];
if (this.activeRunwayCrosswindComponent > 4.5) {
tags.push("crosswind");
}
if (this.weather?.windSpeed && this.weather.windSpeed >= 22) {
tags.push("windy");
}
if (this.weather?.visibility && this.weather.visibility <= 3) {
tags.push("low_visibility");
}
if (Formatter.getLocalDaytime(this.date, this.airport.nauticalTimezone) === "night") {
tags.push("night");
}
if (this.activeRunway?.ilsFrequency) {
tags.push("instruments");
}
if(this.activeRunway?.dimension[0] && this.activeRunway.dimension[0] <= 2000) {
tags.push("short_runway");
}
return tags;
}
/**
* @returns {string?}

@@ -410,9 +437,10 @@ */

/**
* @param {import('./AviationWeatherApi.js').AviationWeatherApiMetar} weatherJson
* @param {import('./AviationWeatherApi.js').AviationWeatherApiMetar} weatherApiData
*/
constructor(weatherJson) {
constructor(weatherApiData) {
const weather = new AviationWeatherNormalizedMetar(weatherApiData);
/**
* @type {number} in degree
*/
this.windDirection = weatherJson.wdir === "VRB" ? 0 : Degree(weatherJson.wdir);
this.windDirection = weather.wdir ?? 0;

@@ -422,3 +450,3 @@ /**

*/
this.windSpeed = weatherJson.wspd;
this.windSpeed = weather.wspd;

@@ -428,3 +456,3 @@ /**

*/
this.windGusts = weatherJson.wgst ?? 0;
this.windGusts = weather.wgst ?? 0;

@@ -434,6 +462,6 @@ /**

*/
this.visibility = typeof weatherJson.visib === "string" ? 15 : weatherJson.visib;
this.visibility = Math.min(15, weather.visib);
this.clouds = weatherJson.clouds.map((c) => {
return new ScenarioWeatherCloud(c.cover, c.base);
this.clouds = weather.clouds.map((c) => {
return new ScenarioWeatherCloud(c);
});

@@ -444,3 +472,3 @@

*/
this.temperature = weatherJson.temp;
this.temperature = weather.temp;
}

@@ -458,60 +486,29 @@

/**
* @type {number} 0..1
* @param {import('./AviationWeatherApi.js').AviationWeatherNormalizedCloud} cloud
*/
#cloudCover = 0;
/**
* @type {"CLR"|"FEW"|"SCT"|"BKN"|"OVC"}
*/
#cloudCoverCode = "CLR";
/**
* @param {"CAVOK"|"CLR"|"FEW"|"SCT"|"BKN"|"OVC"} cover
* @param {number?} base
*/
constructor(cover, base) {
this.cloudCoverCode = cover;
constructor(cloud) {
/**
* @type {number} in ft
* @type {"CLR"|"FEW"|"SCT"|"BKN"|"OVC"}
*/
this.cloudBase = base ?? 0;
}
/**
* @returns {number} 0..1
*/
get cloudCover() {
return this.#cloudCover;
}
this.cloudCoverCode = cloud.cover;
/**
*
* @param {"CAVOK"|"CLR"|"FEW"|"SCT"|"BKN"|"OVC"} cloudCoverCode
*/
set cloudCoverCode(cloudCoverCode) {
if (cloudCoverCode === "CAVOK") {
cloudCoverCode = "CLR";
}
this.#cloudCoverCode = cloudCoverCode;
/**
* @type {{[key:string]:[number,number]}}
*/
const cover = {
CLR: [0, 0], // 0
FEW: [1 / 8, 1 / 8], // 1/8
SCT: [2 / 8, 2 / 8], // 2/8
BKN: [4 / 8, 3 / 8], // 4/8
OVC: [7 / 8, 1 / 8], // 1
FEW: [1 / 8, 1 / 8], // 1/8 .. 2/8
SCT: [2 / 8, 2 / 8], // 2/8 .. 4/8
BKN: [4 / 8, 3 / 8], // 4/8 .. 7/8
OVC: [7 / 8, 1 / 8], // 7/8 .. 1
};
const actualCover = cover[cloudCoverCode] ? cover[cloudCoverCode] : cover.CLR;
const actualCover = cover[this.cloudCoverCode] ? cover[this.cloudCoverCode] : cover.CLR;
this.#cloudCover = actualCover[0] + Math.random() * actualCover[1];
}
/**
* @type {number} 0..1
*/
this.cloudCover = actualCover[0] + Math.random() * actualCover[1];
/**
* @returns {"CLR"|"FEW"|"SCT"|"BKN"|"OVC"}
*/
get cloudCoverCode() {
return this.#cloudCoverCode;
/**
* @type {number} in ft
*/
this.cloudBase = cloud.base ?? 0;
}
}
{
"name": "@fboes/aerofly-patterns",
"version": "2.3.6",
"version": "2.3.7",
"description": "Landegerät - Create landing pattern lessons for Aerofly FS 4.",

@@ -30,3 +30,3 @@ "main": "dist/index.js",

"dependencies": {
"@fboes/aerofly-custom-missions": "^1.0.0",
"@fboes/aerofly-custom-missions": "^1.1.0",
"@fboes/geojson": "^1.4.0"

@@ -33,0 +33,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