node-red-contrib-web-worldmap 5.5.3 → 5.5.6
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/CHANGELOG.md +1 -0
- package/README.md +1 -0
- package/node_modules/@turf/bezier-spline/dist/cjs/index.cjs +2 -2
- package/node_modules/@turf/bezier-spline/dist/cjs/index.cjs.map +1 -1
- package/node_modules/@turf/bezier-spline/dist/esm/index.js +2 -2
- package/node_modules/@turf/bezier-spline/dist/esm/index.js.map +1 -1
- package/node_modules/@turf/bezier-spline/package.json +11 -12
- package/node_modules/@turf/helpers/README.md +1 -1
- package/node_modules/@turf/helpers/dist/cjs/index.cjs.map +1 -1
- package/node_modules/@turf/helpers/dist/cjs/index.d.cts +6 -4
- package/node_modules/@turf/helpers/dist/esm/index.d.ts +6 -4
- package/node_modules/@turf/helpers/dist/esm/index.js.map +1 -1
- package/node_modules/@turf/helpers/package.json +8 -9
- package/node_modules/@turf/invariant/package.json +9 -10
- package/node_modules/express/History.md +11 -0
- package/node_modules/express/package.json +17 -17
- package/node_modules/qs/.github/SECURITY.md +11 -0
- package/node_modules/qs/.github/THREAT_MODEL.md +78 -0
- package/node_modules/qs/CHANGELOG.md +31 -0
- package/node_modules/qs/README.md +25 -1
- package/node_modules/qs/dist/qs.js +95 -44
- package/node_modules/qs/eslint.config.mjs +56 -0
- package/node_modules/qs/lib/parse.js +107 -43
- package/node_modules/qs/lib/stringify.js +11 -6
- package/node_modules/qs/lib/utils.js +61 -6
- package/node_modules/qs/package.json +15 -12
- package/node_modules/qs/test/parse.js +257 -31
- package/node_modules/qs/test/stringify.js +23 -11
- package/node_modules/qs/test/utils.js +245 -0
- package/package.json +8 -3
- package/worldmap/worldmap.js +20 -6
- package/node_modules/qs/.eslintrc +0 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../index.ts"],"sourcesContent":["import {\n BBox,\n Feature,\n FeatureCollection,\n Geometry,\n GeometryCollection,\n GeometryObject,\n LineString,\n MultiLineString,\n MultiPoint,\n MultiPolygon,\n Point,\n Polygon,\n Position,\n GeoJsonProperties,\n} from \"geojson\";\n\nimport { Id } from \"./lib/geojson.js\";\nexport * from \"./lib/geojson.js\";\n\n/**\n * @module helpers\n */\n\n// TurfJS Combined Types\nexport type Coord = Feature<Point> | Point | Position;\n\n/**\n * Linear measurement units.\n *\n * ⚠️ Warning. Be aware of the implications of using radian or degree units to\n * measure distance. The distance represented by a degree of longitude *varies*\n * depending on latitude.\n *\n * See https://www.thoughtco.com/degree-of-latitude-and-longitude-distance-4070616\n * for an illustration of this behaviour.\n *\n * @typedef\n */\nexport type Units =\n | \"meters\"\n | \"metres\"\n | \"millimeters\"\n | \"millimetres\"\n | \"centimeters\"\n | \"centimetres\"\n | \"kilometers\"\n | \"kilometres\"\n | \"miles\"\n | \"nauticalmiles\"\n | \"inches\"\n | \"yards\"\n | \"feet\"\n | \"radians\"\n | \"degrees\";\n\n/**\n * Area measurement units.\n *\n * @typedef\n */\nexport type AreaUnits =\n | Exclude<Units, \"radians\" | \"degrees\">\n | \"acres\"\n | \"hectares\";\n\n/**\n * Grid types.\n *\n * @typedef\n */\nexport type Grid = \"point\" | \"square\" | \"hex\" | \"triangle\";\n\n/**\n * Shorthand corner identifiers.\n *\n * @typedef\n */\nexport type Corners = \"sw\" | \"se\" | \"nw\" | \"ne\" | \"center\" | \"centroid\";\n\n/**\n * Geometries made up of lines i.e. lines and polygons.\n *\n * @typedef\n */\nexport type Lines = LineString | MultiLineString | Polygon | MultiPolygon;\n\n/**\n * Convenience type for all possible GeoJSON.\n *\n * @typedef\n */\nexport type AllGeoJSON =\n | Feature\n | FeatureCollection\n | Geometry\n | GeometryCollection;\n\n/**\n * The Earth radius in kilometers. Used by Turf modules that model the Earth as a sphere. The {@link https://en.wikipedia.org/wiki/Earth_radius#Arithmetic_mean_radius mean radius} was selected because it is {@link https://rosettacode.org/wiki/Haversine_formula#:~:text=This%20value%20is%20recommended recommended } by the Haversine formula (used by turf/distance) to reduce error.\n *\n * @constant\n */\nexport const earthRadius = 6371008.8;\n\n/**\n * Unit of measurement factors based on earthRadius.\n *\n * Keys are the name of the unit, values are the number of that unit in a single radian\n *\n * @constant\n */\nexport const factors: Record<Units, number> = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: 360 / (2 * Math.PI),\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1000,\n kilometres: earthRadius / 1000,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1000,\n millimetres: earthRadius * 1000,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936,\n};\n\n/**\n\n * Area of measurement factors based on 1 square meter.\n *\n * @constant\n */\nexport const areaFactors: Record<AreaUnits, number> = {\n acres: 0.000247105,\n centimeters: 10000,\n centimetres: 10000,\n feet: 10.763910417,\n hectares: 0.0001,\n inches: 1550.003100006,\n kilometers: 0.000001,\n kilometres: 0.000001,\n meters: 1,\n metres: 1,\n miles: 3.86e-7,\n nauticalmiles: 2.9155334959812285e-7,\n millimeters: 1000000,\n millimetres: 1000000,\n yards: 1.195990046,\n};\n\n/**\n * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.\n *\n * @function\n * @param {GeometryObject} geometry input geometry\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<GeometryObject, GeoJsonProperties>} a GeoJSON Feature\n * @example\n * var geometry = {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 50]\n * };\n *\n * var feature = turf.feature(geometry);\n *\n * //=feature\n */\nexport function feature<\n G extends GeometryObject = Geometry,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geom: G | null,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<G, P> {\n const feat: any = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\n\n/**\n * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates.\n * For GeometryCollection type use `helpers.geometryCollection`\n *\n * @function\n * @param {(\"Point\" | \"LineString\" | \"Polygon\" | \"MultiPoint\" | \"MultiLineString\" | \"MultiPolygon\")} type Geometry Type\n * @param {Array<any>} coordinates Coordinates\n * @param {Object} [options={}] Optional Parameters\n * @returns {Geometry} a GeoJSON Geometry\n * @example\n * var type = \"Point\";\n * var coordinates = [110, 50];\n * var geometry = turf.geometry(type, coordinates);\n * // => geometry\n */\nexport function geometry(\n type:\n | \"Point\"\n | \"LineString\"\n | \"Polygon\"\n | \"MultiPoint\"\n | \"MultiLineString\"\n | \"MultiPolygon\",\n coordinates: any[],\n _options: Record<string, never> = {}\n) {\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\n\n/**\n * Creates a {@link Point} {@link Feature} from a Position.\n *\n * @function\n * @param {Position} coordinates longitude, latitude position (each in decimal degrees)\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<Point, GeoJsonProperties>} a Point feature\n * @example\n * var point = turf.point([-75.343, 39.984]);\n *\n * //=point\n */\nexport function point<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<Point, P> {\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n\n const geom: Point = {\n type: \"Point\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates.\n *\n * @function\n * @param {Position[]} coordinates an array of Points\n * @param {GeoJsonProperties} [properties={}] Translate these properties to each Feature\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<Point>} Point Feature\n * @example\n * var points = turf.points([\n * [-75, 39],\n * [-80, 45],\n * [-78, 50]\n * ]);\n *\n * //=points\n */\nexport function points<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<Point, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return point(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.\n *\n * @function\n * @param {Position[][]} coordinates an array of LinearRings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<Polygon, GeoJsonProperties>} Polygon Feature\n * @example\n * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });\n *\n * //=polygon\n */\nexport function polygon<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<Polygon, P> {\n for (const ring of coordinates) {\n if (ring.length < 4) {\n throw new Error(\n \"Each LinearRing of a Polygon must have 4 or more Positions.\"\n );\n }\n\n if (ring[ring.length - 1].length !== ring[0].length) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n\n for (let j = 0; j < ring[ring.length - 1].length; j++) {\n // Check if first point of Polygon contains two numbers\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n const geom: Polygon = {\n type: \"Polygon\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates.\n *\n * @function\n * @param {Position[][][]} coordinates an array of Polygon coordinates\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<Polygon, GeoJsonProperties>} Polygon FeatureCollection\n * @example\n * var polygons = turf.polygons([\n * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]],\n * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]],\n * ]);\n *\n * //=polygons\n */\nexport function polygons<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<Polygon, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return polygon(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Creates a {@link LineString} {@link Feature} from an Array of Positions.\n *\n * @function\n * @param {Position[]} coordinates an array of Positions\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<LineString, GeoJsonProperties>} LineString Feature\n * @example\n * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});\n * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});\n *\n * //=linestring1\n * //=linestring2\n */\nexport function lineString<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<LineString, P> {\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n const geom: LineString = {\n type: \"LineString\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates.\n *\n * @function\n * @param {Position[][]} coordinates an array of LinearRings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<LineString, GeoJsonProperties>} LineString FeatureCollection\n * @example\n * var linestrings = turf.lineStrings([\n * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]],\n * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]]\n * ]);\n *\n * //=linestrings\n */\nexport function lineStrings<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<LineString, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return lineString(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}.\n *\n * @function\n * @param {Array<Feature<GeometryObject, GeoJsonProperties>>} features input features\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {FeatureCollection<GeometryObject, GeoJsonProperties>} FeatureCollection of Features\n * @example\n * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'});\n * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'});\n * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'});\n *\n * var collection = turf.featureCollection([\n * locationA,\n * locationB,\n * locationC\n * ]);\n *\n * //=collection\n */\nexport function featureCollection<\n G extends GeometryObject = Geometry,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n features: Array<Feature<G, P>>,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<G, P> {\n const fc: any = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiLineString}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[][]} coordinates an array of LineStrings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiLineString, GeoJsonProperties>} a MultiLineString feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);\n *\n * //=multiLine\n */\nexport function multiLineString<\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiLineString, P> {\n const geom: MultiLineString = {\n type: \"MultiLineString\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiPoint}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[]} coordinates an array of Positions\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiPoint, GeoJsonProperties>} a MultiPoint feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPt = turf.multiPoint([[0,0],[10,10]]);\n *\n * //=multiPt\n */\nexport function multiPoint<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiPoint, P> {\n const geom: MultiPoint = {\n type: \"MultiPoint\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiPolygon}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[][][]} coordinates an array of Polygons\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiPolygon, GeoJsonProperties>} a multipolygon feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);\n *\n * //=multiPoly\n *\n */\nexport function multiPolygon<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiPolygon, P> {\n const geom: MultiPolygon = {\n type: \"MultiPolygon\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a Feature<GeometryCollection> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Array<Point | LineString | Polygon | MultiPoint | MultiLineString | MultiPolygon>} geometries an array of GeoJSON Geometries\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<GeometryCollection, GeoJsonProperties>} a GeoJSON GeometryCollection Feature\n * @example\n * var pt = turf.geometry(\"Point\", [100, 0]);\n * var line = turf.geometry(\"LineString\", [[101, 0], [102, 1]]);\n * var collection = turf.geometryCollection([pt, line]);\n *\n * // => collection\n */\nexport function geometryCollection<\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geometries: Array<\n Point | LineString | Polygon | MultiPoint | MultiLineString | MultiPolygon\n >,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<GeometryCollection, P> {\n const geom: GeometryCollection = {\n type: \"GeometryCollection\",\n geometries,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Round number to precision\n *\n * @function\n * @param {number} num Number\n * @param {number} [precision=0] Precision\n * @returns {number} rounded number\n * @example\n * turf.round(120.4321)\n * //=120\n *\n * turf.round(120.4321, 2)\n * //=120.43\n */\nexport function round(num: number, precision = 0): number {\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n const multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @function\n * @param {number} radians in radians across the sphere\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} distance\n */\nexport function radiansToLength(\n radians: number,\n units: Units = \"kilometers\"\n): number {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @function\n * @param {number} distance in real units\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} radians\n */\nexport function lengthToRadians(\n distance: number,\n units: Units = \"kilometers\"\n): number {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet\n *\n * @function\n * @param {number} distance in real units\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} degrees\n */\nexport function lengthToDegrees(distance: number, units?: Units): number {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\n\n/**\n * Converts any bearing angle from the north line direction (positive clockwise)\n * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line\n *\n * @function\n * @param {number} bearing angle, between -180 and +180 degrees\n * @returns {number} angle between 0 and 360 degrees\n */\nexport function bearingToAzimuth(bearing: number): number {\n let angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\n\n/**\n * Converts any azimuth angle from the north line direction (positive clockwise)\n * and returns an angle between -180 and +180 degrees (positive clockwise), 0 being the north line\n *\n * @function\n * @param {number} angle between 0 and 360 degrees\n * @returns {number} bearing between -180 and +180 degrees\n */\nexport function azimuthToBearing(angle: number): number {\n // Ignore full revolutions (multiples of 360)\n angle = angle % 360;\n\n if (angle > 180) {\n return angle - 360;\n } else if (angle < -180) {\n return angle + 360;\n }\n\n return angle;\n}\n\n/**\n * Converts an angle in radians to degrees\n *\n * @function\n * @param {number} radians angle in radians\n * @returns {number} degrees between 0 and 360 degrees\n */\nexport function radiansToDegrees(radians: number): number {\n // % (2 * Math.PI) radians in case someone passes value > 2π\n const normalisedRadians = radians % (2 * Math.PI);\n return (normalisedRadians * 180) / Math.PI;\n}\n\n/**\n * Converts an angle in degrees to radians\n *\n * @function\n * @param {number} degrees angle between 0 and 360 degrees\n * @returns {number} angle in radians\n */\nexport function degreesToRadians(degrees: number): number {\n // % 360 degrees in case someone passes value > 360\n const normalisedDegrees = degrees % 360;\n return (normalisedDegrees * Math.PI) / 180;\n}\n\n/**\n * Converts a length from one unit to another.\n *\n * @function\n * @param {number} length Length to be converted\n * @param {Units} [originalUnit=\"kilometers\"] Input length unit\n * @param {Units} [finalUnit=\"kilometers\"] Returned length unit\n * @returns {number} The converted length\n */\nexport function convertLength(\n length: number,\n originalUnit: Units = \"kilometers\",\n finalUnit: Units = \"kilometers\"\n): number {\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\n\n/**\n * Converts an area from one unit to another.\n *\n * @function\n * @param {number} area Area to be converted\n * @param {AreaUnits} [originalUnit=\"meters\"] Input area unit\n * @param {AreaUnits} [finalUnit=\"kilometers\"] Returned area unit\n * @returns {number} The converted length\n */\nexport function convertArea(\n area: number,\n originalUnit: AreaUnits = \"meters\",\n finalUnit: AreaUnits = \"kilometers\"\n): number {\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n\n const startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n\n const finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n\n return (area / startFactor) * finalFactor;\n}\n\n/**\n * isNumber\n *\n * @function\n * @param {any} num Number to validate\n * @returns {boolean} true/false\n * @example\n * turf.isNumber(123)\n * //=true\n * turf.isNumber('foo')\n * //=false\n */\nexport function isNumber(num: any): boolean {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\n\n/**\n * isObject\n *\n * @function\n * @param {any} input variable to validate\n * @returns {boolean} true/false, including false for Arrays and Functions\n * @example\n * turf.isObject({elevation: 10})\n * //=true\n * turf.isObject('foo')\n * //=false\n */\nexport function isObject(input: any): boolean {\n return input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\n\n/**\n * Validate BBox\n *\n * @private\n * @param {any} bbox BBox to validate\n * @returns {void}\n * @throws {Error} if BBox is not valid\n * @example\n * validateBBox([-180, -40, 110, 50])\n * //=OK\n * validateBBox([-180, -40])\n * //=Error\n * validateBBox('Foo')\n * //=Error\n * validateBBox(5)\n * //=Error\n * validateBBox(null)\n * //=Error\n * validateBBox(undefined)\n * //=Error\n */\nexport function validateBBox(bbox: any): void {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach((num) => {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\n\n/**\n * Validate Id\n *\n * @private\n * @param {any} id Id to validate\n * @returns {void}\n * @throws {Error} if Id is not valid\n * @example\n * validateId([-180, -40, 110, 50])\n * //=Error\n * validateId([-180, -40])\n * //=Error\n * validateId('Foo')\n * //=OK\n * validateId(5)\n * //=OK\n * validateId(null)\n * //=Error\n * validateId(undefined)\n * //=Error\n */\nexport function validateId(id: any): void {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../index.ts"],"sourcesContent":["import {\n BBox,\n Feature,\n FeatureCollection,\n Geometry,\n GeometryCollection,\n GeometryObject,\n LineString,\n MultiLineString,\n MultiPoint,\n MultiPolygon,\n Point,\n Polygon,\n Position,\n GeoJsonProperties,\n} from \"geojson\";\n\nimport { Id } from \"./lib/geojson.js\";\nexport * from \"./lib/geojson.js\";\n\n/**\n * @module helpers\n */\n\n// TurfJS Combined Types\nexport type Coord = Feature<Point> | Point | Position;\n\n/**\n * Linear measurement units.\n *\n * ⚠️ Warning. Be aware of the implications of using radian or degree units to\n * measure distance. The distance represented by a degree of longitude *varies*\n * depending on latitude.\n *\n * See https://www.thoughtco.com/degree-of-latitude-and-longitude-distance-4070616\n * for an illustration of this behaviour.\n *\n * @typedef\n */\nexport type Units =\n | \"meters\"\n | \"metres\"\n | \"millimeters\"\n | \"millimetres\"\n | \"centimeters\"\n | \"centimetres\"\n | \"kilometers\"\n | \"kilometres\"\n | \"miles\"\n | \"nauticalmiles\"\n | \"inches\"\n | \"yards\"\n | \"feet\"\n | \"radians\"\n | \"degrees\";\n\n/**\n * Area measurement units.\n *\n * @typedef\n */\nexport type AreaUnits =\n | Exclude<Units, \"radians\" | \"degrees\">\n | \"acres\"\n | \"hectares\";\n\n/**\n * Grid types.\n *\n * @typedef\n */\nexport type Grid = \"point\" | \"square\" | \"hex\" | \"triangle\";\n\n/**\n * Shorthand corner identifiers.\n *\n * @typedef\n */\nexport type Corners = \"sw\" | \"se\" | \"nw\" | \"ne\" | \"center\" | \"centroid\";\n\n/**\n * Geometries made up of lines i.e. lines and polygons.\n *\n * @typedef\n */\nexport type Lines = LineString | MultiLineString | Polygon | MultiPolygon;\n\n/**\n * Convenience type for all possible GeoJSON.\n *\n * @typedef\n */\nexport type AllGeoJSON =\n | Feature\n | FeatureCollection\n | Geometry\n | GeometryCollection;\n\n/**\n * The Earth radius in meters. Used by Turf modules that model the Earth as a sphere. The {@link https://en.wikipedia.org/wiki/Earth_radius#Arithmetic_mean_radius mean radius} was selected because it is {@link https://rosettacode.org/wiki/Haversine_formula#:~:text=This%20value%20is%20recommended recommended } by the Haversine formula (used by turf/distance) to reduce error.\n *\n * @constant\n */\nexport const earthRadius = 6371008.8;\n\n/**\n * Unit of measurement factors based on earthRadius.\n *\n * Keys are the name of the unit, values are the number of that unit in a single radian\n *\n * @constant\n */\nexport const factors: Record<Units, number> = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: 360 / (2 * Math.PI),\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1000,\n kilometres: earthRadius / 1000,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1000,\n millimetres: earthRadius * 1000,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936,\n};\n\n/**\n\n * Area of measurement factors based on 1 square meter.\n *\n * @constant\n */\nexport const areaFactors: Record<AreaUnits, number> = {\n acres: 0.000247105,\n centimeters: 10000,\n centimetres: 10000,\n feet: 10.763910417,\n hectares: 0.0001,\n inches: 1550.003100006,\n kilometers: 0.000001,\n kilometres: 0.000001,\n meters: 1,\n metres: 1,\n miles: 3.86e-7,\n nauticalmiles: 2.9155334959812285e-7,\n millimeters: 1000000,\n millimetres: 1000000,\n yards: 1.195990046,\n};\n\n/**\n * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.\n *\n * @function\n * @param {GeometryObject} geometry input geometry\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<GeometryObject, GeoJsonProperties>} a GeoJSON Feature\n * @example\n * var geometry = {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 50]\n * };\n *\n * var feature = turf.feature(geometry);\n *\n * //=feature\n */\nexport function feature<\n G extends GeometryObject = Geometry,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geom: G | null,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<G, P> {\n const feat: any = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\n\n/**\n * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates.\n * For GeometryCollection type use `helpers.geometryCollection`\n *\n * @function\n * @param {(\"Point\" | \"LineString\" | \"Polygon\" | \"MultiPoint\" | \"MultiLineString\" | \"MultiPolygon\")} type Geometry Type\n * @param {Array<any>} coordinates Coordinates\n * @param {Object} [options={}] Optional Parameters\n * @returns {Geometry} a GeoJSON Geometry\n * @example\n * var type = \"Point\";\n * var coordinates = [110, 50];\n * var geometry = turf.geometry(type, coordinates);\n * // => geometry\n */\nexport function geometry<\n T extends\n | \"Point\"\n | \"LineString\"\n | \"Polygon\"\n | \"MultiPoint\"\n | \"MultiLineString\"\n | \"MultiPolygon\",\n>(\n type: T,\n coordinates: any[],\n _options: Record<string, never> = {}\n): Extract<Geometry, { type: T }> {\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry as Extract<Geometry, { type: T }>;\n case \"LineString\":\n return lineString(coordinates).geometry as Extract<Geometry, { type: T }>;\n case \"Polygon\":\n return polygon(coordinates).geometry as Extract<Geometry, { type: T }>;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry as Extract<Geometry, { type: T }>;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry as Extract<\n Geometry,\n { type: T }\n >;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry as Extract<\n Geometry,\n { type: T }\n >;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\n\n/**\n * Creates a {@link Point} {@link Feature} from a Position.\n *\n * @function\n * @param {Position} coordinates longitude, latitude position (each in decimal degrees)\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<Point, GeoJsonProperties>} a Point feature\n * @example\n * var point = turf.point([-75.343, 39.984]);\n *\n * //=point\n */\nexport function point<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<Point, P> {\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n\n const geom: Point = {\n type: \"Point\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates.\n *\n * @function\n * @param {Position[]} coordinates an array of Points\n * @param {GeoJsonProperties} [properties={}] Translate these properties to each Feature\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<Point>} Point Feature\n * @example\n * var points = turf.points([\n * [-75, 39],\n * [-80, 45],\n * [-78, 50]\n * ]);\n *\n * //=points\n */\nexport function points<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<Point, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return point(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.\n *\n * @function\n * @param {Position[][]} coordinates an array of LinearRings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<Polygon, GeoJsonProperties>} Polygon Feature\n * @example\n * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });\n *\n * //=polygon\n */\nexport function polygon<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<Polygon, P> {\n for (const ring of coordinates) {\n if (ring.length < 4) {\n throw new Error(\n \"Each LinearRing of a Polygon must have 4 or more Positions.\"\n );\n }\n\n if (ring[ring.length - 1].length !== ring[0].length) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n\n for (let j = 0; j < ring[ring.length - 1].length; j++) {\n // Check if first point of Polygon contains two numbers\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n const geom: Polygon = {\n type: \"Polygon\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates.\n *\n * @function\n * @param {Position[][][]} coordinates an array of Polygon coordinates\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<Polygon, GeoJsonProperties>} Polygon FeatureCollection\n * @example\n * var polygons = turf.polygons([\n * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]],\n * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]],\n * ]);\n *\n * //=polygons\n */\nexport function polygons<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<Polygon, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return polygon(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Creates a {@link LineString} {@link Feature} from an Array of Positions.\n *\n * @function\n * @param {Position[]} coordinates an array of Positions\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<LineString, GeoJsonProperties>} LineString Feature\n * @example\n * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});\n * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});\n *\n * //=linestring1\n * //=linestring2\n */\nexport function lineString<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<LineString, P> {\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n const geom: LineString = {\n type: \"LineString\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates.\n *\n * @function\n * @param {Position[][]} coordinates an array of LinearRings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {Id} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection<LineString, GeoJsonProperties>} LineString FeatureCollection\n * @example\n * var linestrings = turf.lineStrings([\n * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]],\n * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]]\n * ]);\n *\n * //=linestrings\n */\nexport function lineStrings<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<LineString, P> {\n return featureCollection(\n coordinates.map((coords) => {\n return lineString(coords, properties);\n }),\n options\n );\n}\n\n/**\n * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}.\n *\n * @function\n * @param {Array<Feature<GeometryObject, GeoJsonProperties>>} features input features\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {FeatureCollection<GeometryObject, GeoJsonProperties>} FeatureCollection of Features\n * @example\n * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'});\n * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'});\n * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'});\n *\n * var collection = turf.featureCollection([\n * locationA,\n * locationB,\n * locationC\n * ]);\n *\n * //=collection\n */\nexport function featureCollection<\n G extends GeometryObject = Geometry,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n features: Array<Feature<G, P>>,\n options: { bbox?: BBox; id?: Id } = {}\n): FeatureCollection<G, P> {\n const fc: any = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiLineString}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[][]} coordinates an array of LineStrings\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiLineString, GeoJsonProperties>} a MultiLineString feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);\n *\n * //=multiLine\n */\nexport function multiLineString<\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n coordinates: Position[][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiLineString, P> {\n const geom: MultiLineString = {\n type: \"MultiLineString\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiPoint}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[]} coordinates an array of Positions\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiPoint, GeoJsonProperties>} a MultiPoint feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPt = turf.multiPoint([[0,0],[10,10]]);\n *\n * //=multiPt\n */\nexport function multiPoint<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiPoint, P> {\n const geom: MultiPoint = {\n type: \"MultiPoint\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a {@link Feature}<{@link MultiPolygon}> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Position[][][]} coordinates an array of Polygons\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<MultiPolygon, GeoJsonProperties>} a multipolygon feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);\n *\n * //=multiPoly\n *\n */\nexport function multiPolygon<P extends GeoJsonProperties = GeoJsonProperties>(\n coordinates: Position[][][],\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<MultiPolygon, P> {\n const geom: MultiPolygon = {\n type: \"MultiPolygon\",\n coordinates,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Creates a Feature<GeometryCollection> based on a\n * coordinate array. Properties can be added optionally.\n *\n * @function\n * @param {Array<Point | LineString | Polygon | MultiPoint | MultiLineString | MultiPolygon>} geometries an array of GeoJSON Geometries\n * @param {GeoJsonProperties} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {BBox} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {Id} [options.id] Identifier associated with the Feature\n * @returns {Feature<GeometryCollection, GeoJsonProperties>} a GeoJSON GeometryCollection Feature\n * @example\n * var pt = turf.geometry(\"Point\", [100, 0]);\n * var line = turf.geometry(\"LineString\", [[101, 0], [102, 1]]);\n * var collection = turf.geometryCollection([pt, line]);\n *\n * // => collection\n */\nexport function geometryCollection<\n G extends\n | Point\n | LineString\n | Polygon\n | MultiPoint\n | MultiLineString\n | MultiPolygon,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geometries: Array<G>,\n properties?: P,\n options: { bbox?: BBox; id?: Id } = {}\n): Feature<GeometryCollection<G>, P> {\n const geom: GeometryCollection<G> = {\n type: \"GeometryCollection\",\n geometries,\n };\n return feature(geom, properties, options);\n}\n\n/**\n * Round number to precision\n *\n * @function\n * @param {number} num Number\n * @param {number} [precision=0] Precision\n * @returns {number} rounded number\n * @example\n * turf.round(120.4321)\n * //=120\n *\n * turf.round(120.4321, 2)\n * //=120.43\n */\nexport function round(num: number, precision = 0): number {\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n const multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @function\n * @param {number} radians in radians across the sphere\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} distance\n */\nexport function radiansToLength(\n radians: number,\n units: Units = \"kilometers\"\n): number {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @function\n * @param {number} distance in real units\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} radians\n */\nexport function lengthToRadians(\n distance: number,\n units: Units = \"kilometers\"\n): number {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\n\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet\n *\n * @function\n * @param {number} distance in real units\n * @param {Units} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} degrees\n */\nexport function lengthToDegrees(distance: number, units?: Units): number {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\n\n/**\n * Converts any bearing angle from the north line direction (positive clockwise)\n * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line\n *\n * @function\n * @param {number} bearing angle, between -180 and +180 degrees\n * @returns {number} angle between 0 and 360 degrees\n */\nexport function bearingToAzimuth(bearing: number): number {\n let angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\n\n/**\n * Converts any azimuth angle from the north line direction (positive clockwise)\n * and returns an angle between -180 and +180 degrees (positive clockwise), 0 being the north line\n *\n * @function\n * @param {number} angle between 0 and 360 degrees\n * @returns {number} bearing between -180 and +180 degrees\n */\nexport function azimuthToBearing(angle: number): number {\n // Ignore full revolutions (multiples of 360)\n angle = angle % 360;\n\n if (angle > 180) {\n return angle - 360;\n } else if (angle < -180) {\n return angle + 360;\n }\n\n return angle;\n}\n\n/**\n * Converts an angle in radians to degrees\n *\n * @function\n * @param {number} radians angle in radians\n * @returns {number} degrees between 0 and 360 degrees\n */\nexport function radiansToDegrees(radians: number): number {\n // % (2 * Math.PI) radians in case someone passes value > 2π\n const normalisedRadians = radians % (2 * Math.PI);\n return (normalisedRadians * 180) / Math.PI;\n}\n\n/**\n * Converts an angle in degrees to radians\n *\n * @function\n * @param {number} degrees angle between 0 and 360 degrees\n * @returns {number} angle in radians\n */\nexport function degreesToRadians(degrees: number): number {\n // % 360 degrees in case someone passes value > 360\n const normalisedDegrees = degrees % 360;\n return (normalisedDegrees * Math.PI) / 180;\n}\n\n/**\n * Converts a length from one unit to another.\n *\n * @function\n * @param {number} length Length to be converted\n * @param {Units} [originalUnit=\"kilometers\"] Input length unit\n * @param {Units} [finalUnit=\"kilometers\"] Returned length unit\n * @returns {number} The converted length\n */\nexport function convertLength(\n length: number,\n originalUnit: Units = \"kilometers\",\n finalUnit: Units = \"kilometers\"\n): number {\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\n\n/**\n * Converts an area from one unit to another.\n *\n * @function\n * @param {number} area Area to be converted\n * @param {AreaUnits} [originalUnit=\"meters\"] Input area unit\n * @param {AreaUnits} [finalUnit=\"kilometers\"] Returned area unit\n * @returns {number} The converted length\n */\nexport function convertArea(\n area: number,\n originalUnit: AreaUnits = \"meters\",\n finalUnit: AreaUnits = \"kilometers\"\n): number {\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n\n const startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n\n const finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n\n return (area / startFactor) * finalFactor;\n}\n\n/**\n * isNumber\n *\n * @function\n * @param {any} num Number to validate\n * @returns {boolean} true/false\n * @example\n * turf.isNumber(123)\n * //=true\n * turf.isNumber('foo')\n * //=false\n */\nexport function isNumber(num: any): boolean {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\n\n/**\n * isObject\n *\n * @function\n * @param {any} input variable to validate\n * @returns {boolean} true/false, including false for Arrays and Functions\n * @example\n * turf.isObject({elevation: 10})\n * //=true\n * turf.isObject('foo')\n * //=false\n */\nexport function isObject(input: any): boolean {\n return input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\n\n/**\n * Validate BBox\n *\n * @private\n * @param {any} bbox BBox to validate\n * @returns {void}\n * @throws {Error} if BBox is not valid\n * @example\n * validateBBox([-180, -40, 110, 50])\n * //=OK\n * validateBBox([-180, -40])\n * //=Error\n * validateBBox('Foo')\n * //=Error\n * validateBBox(5)\n * //=Error\n * validateBBox(null)\n * //=Error\n * validateBBox(undefined)\n * //=Error\n */\nexport function validateBBox(bbox: any): void {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach((num) => {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\n\n/**\n * Validate Id\n *\n * @private\n * @param {any} id Id to validate\n * @returns {void}\n * @throws {Error} if Id is not valid\n * @example\n * validateId([-180, -40, 110, 50])\n * //=Error\n * validateId([-180, -40])\n * //=Error\n * validateId('Foo')\n * //=OK\n * validateId(5)\n * //=OK\n * validateId(null)\n * //=Error\n * validateId(undefined)\n * //=Error\n */\nexport function validateId(id: any): void {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/helpers",
|
|
3
|
-
"version": "7.2
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "7.3.2",
|
|
4
|
+
"description": "Provides helper functions to create GeoJSON features, like points, lines, or areas on a map.",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Tom MacWright <@tmcw>",
|
|
@@ -53,23 +53,22 @@
|
|
|
53
53
|
"bench": "tsx bench.ts",
|
|
54
54
|
"build": "tsup --config ../../tsup.config.ts",
|
|
55
55
|
"docs": "tsx ../../scripts/generate-readmes.ts",
|
|
56
|
-
"test": "
|
|
56
|
+
"test": "pnpm run /test:.*/",
|
|
57
57
|
"test:tape": "tsx test.ts",
|
|
58
58
|
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/benchmark": "^2.1.5",
|
|
62
|
-
"@types/tape": "^
|
|
62
|
+
"@types/tape": "^5.8.1",
|
|
63
63
|
"benchmark": "^2.1.4",
|
|
64
|
-
"npm-run-all": "^4.1.5",
|
|
65
64
|
"tape": "^5.9.0",
|
|
66
|
-
"tsup": "^8.
|
|
67
|
-
"tsx": "^4.19.
|
|
68
|
-
"typescript": "^5.
|
|
65
|
+
"tsup": "^8.4.0",
|
|
66
|
+
"tsx": "^4.19.4",
|
|
67
|
+
"typescript": "^5.8.3"
|
|
69
68
|
},
|
|
70
69
|
"dependencies": {
|
|
71
70
|
"@types/geojson": "^7946.0.10",
|
|
72
71
|
"tslib": "^2.8.1"
|
|
73
72
|
},
|
|
74
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "099d9915467bacf45d554be4533fa9998c4efc88"
|
|
75
74
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/invariant",
|
|
3
|
-
"version": "7.2
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "7.3.2",
|
|
4
|
+
"description": "Lightweight utility for input validation and data extraction in Turf.js. Ensures GeoJSON inputs are in the correct format and extracts specific components like coordinates or geometries.",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Tom MacWright <@tmcw>",
|
|
@@ -50,24 +50,23 @@
|
|
|
50
50
|
"bench": "tsx bench.ts",
|
|
51
51
|
"build": "tsup --config ../../tsup.config.ts",
|
|
52
52
|
"docs": "tsx ../../scripts/generate-readmes.ts",
|
|
53
|
-
"test": "
|
|
53
|
+
"test": "pnpm run /test:.*/",
|
|
54
54
|
"test:tape": "tsx test.ts",
|
|
55
55
|
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/benchmark": "^2.1.5",
|
|
59
|
-
"@types/tape": "^
|
|
59
|
+
"@types/tape": "^5.8.1",
|
|
60
60
|
"benchmark": "^2.1.4",
|
|
61
|
-
"npm-run-all": "^4.1.5",
|
|
62
61
|
"tape": "^5.9.0",
|
|
63
|
-
"tsup": "^8.
|
|
64
|
-
"tsx": "^4.19.
|
|
65
|
-
"typescript": "^5.
|
|
62
|
+
"tsup": "^8.4.0",
|
|
63
|
+
"tsx": "^4.19.4",
|
|
64
|
+
"typescript": "^5.8.3"
|
|
66
65
|
},
|
|
67
66
|
"dependencies": {
|
|
68
|
-
"@turf/helpers": "
|
|
67
|
+
"@turf/helpers": "7.3.2",
|
|
69
68
|
"@types/geojson": "^7946.0.10",
|
|
70
69
|
"tslib": "^2.8.1"
|
|
71
70
|
},
|
|
72
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "099d9915467bacf45d554be4533fa9998c4efc88"
|
|
73
72
|
}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
4.22.1 / 2025-12-01
|
|
2
|
+
==========
|
|
3
|
+
|
|
4
|
+
* Revert security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
|
|
5
|
+
|
|
6
|
+
4.22.0 / 2025-12-01
|
|
7
|
+
==========
|
|
8
|
+
* Security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
|
|
9
|
+
* deps: use tilde notation for dependencies
|
|
10
|
+
* deps: qs@6.14.0
|
|
11
|
+
|
|
1
12
|
4.21.2 / 2024-11-06
|
|
2
13
|
==========
|
|
3
14
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express",
|
|
3
3
|
"description": "Fast, unopinionated, minimalist web framework",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.22.1",
|
|
5
5
|
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
|
|
@@ -34,32 +34,32 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"accepts": "~1.3.8",
|
|
36
36
|
"array-flatten": "1.1.1",
|
|
37
|
-
"body-parser": "1.20.3",
|
|
38
|
-
"content-disposition": "0.5.4",
|
|
37
|
+
"body-parser": "~1.20.3",
|
|
38
|
+
"content-disposition": "~0.5.4",
|
|
39
39
|
"content-type": "~1.0.4",
|
|
40
|
-
"cookie": "0.7.1",
|
|
41
|
-
"cookie-signature": "1.0.6",
|
|
40
|
+
"cookie": "~0.7.1",
|
|
41
|
+
"cookie-signature": "~1.0.6",
|
|
42
42
|
"debug": "2.6.9",
|
|
43
43
|
"depd": "2.0.0",
|
|
44
44
|
"encodeurl": "~2.0.0",
|
|
45
45
|
"escape-html": "~1.0.3",
|
|
46
46
|
"etag": "~1.8.1",
|
|
47
|
-
"finalhandler": "1.3.1",
|
|
48
|
-
"fresh": "0.5.2",
|
|
49
|
-
"http-errors": "2.0.0",
|
|
47
|
+
"finalhandler": "~1.3.1",
|
|
48
|
+
"fresh": "~0.5.2",
|
|
49
|
+
"http-errors": "~2.0.0",
|
|
50
50
|
"merge-descriptors": "1.0.3",
|
|
51
51
|
"methods": "~1.1.2",
|
|
52
|
-
"on-finished": "2.4.1",
|
|
52
|
+
"on-finished": "~2.4.1",
|
|
53
53
|
"parseurl": "~1.3.3",
|
|
54
|
-
"path-to-regexp": "0.1.12",
|
|
54
|
+
"path-to-regexp": "~0.1.12",
|
|
55
55
|
"proxy-addr": "~2.0.7",
|
|
56
|
-
"qs": "6.
|
|
56
|
+
"qs": "~6.14.0",
|
|
57
57
|
"range-parser": "~1.2.1",
|
|
58
58
|
"safe-buffer": "5.2.1",
|
|
59
|
-
"send": "0.19.0",
|
|
60
|
-
"serve-static": "1.16.2",
|
|
59
|
+
"send": "~0.19.0",
|
|
60
|
+
"serve-static": "~1.16.2",
|
|
61
61
|
"setprototypeof": "1.2.0",
|
|
62
|
-
"statuses": "2.0.1",
|
|
62
|
+
"statuses": "~2.0.1",
|
|
63
63
|
"type-is": "~1.6.18",
|
|
64
64
|
"utils-merge": "1.0.1",
|
|
65
65
|
"vary": "~1.1.2"
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"hbs": "4.2.0",
|
|
76
76
|
"marked": "0.7.0",
|
|
77
77
|
"method-override": "3.0.0",
|
|
78
|
-
"mocha": "
|
|
78
|
+
"mocha": "^6.2.2",
|
|
79
79
|
"morgan": "1.10.0",
|
|
80
|
-
"nyc": "
|
|
80
|
+
"nyc": "^14.1.1",
|
|
81
81
|
"pbkdf2-password": "1.2.1",
|
|
82
|
-
"supertest": "6.
|
|
82
|
+
"supertest": "^6.1.6",
|
|
83
83
|
"vhost": "~3.0.2"
|
|
84
84
|
},
|
|
85
85
|
"engines": {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Please file a private vulnerability report via GitHub, email [@ljharb](https://github.com/ljharb), or see https://tidelift.com/security if you have a potential security vulnerability to report.
|
|
4
|
+
|
|
5
|
+
## Incident Response Plan
|
|
6
|
+
|
|
7
|
+
Please see our [Incident Response Plan](https://github.com/ljharb/.github/blob/main/INCIDENT_RESPONSE_PLAN.md).
|
|
8
|
+
|
|
9
|
+
## Threat Model
|
|
10
|
+
|
|
11
|
+
Please see [THREAT_MODEL.md](./THREAT_MODEL.md).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
## Threat Model for qs (querystring parsing library)
|
|
2
|
+
|
|
3
|
+
### 1. Library Overview
|
|
4
|
+
|
|
5
|
+
- **Library Name:** qs
|
|
6
|
+
- **Brief Description:** A JavaScript library for parsing and stringifying URL query strings, supporting nested objects and arrays. It is widely used in Node.js and web applications for processing query parameters[2][6][8].
|
|
7
|
+
- **Key Public APIs/Functions:** `qs.parse()`, `qs.stringify()`
|
|
8
|
+
|
|
9
|
+
### 2. Define Scope
|
|
10
|
+
|
|
11
|
+
This threat model focuses on the core parsing and stringifying functionality, specifically the handling of nested objects and arrays, option validation, and cycle management in stringification.
|
|
12
|
+
|
|
13
|
+
### 3. Conceptual System Diagram
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Caller Application → qs.parse(input, options) → Parsing Engine → Output Object
|
|
17
|
+
│
|
|
18
|
+
└→ Options Handling
|
|
19
|
+
|
|
20
|
+
Caller Application → qs.stringify(obj, options) → Stringifying Engine → Output String
|
|
21
|
+
│
|
|
22
|
+
└→ Options Handling
|
|
23
|
+
└→ Cycle Tracking
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Trust Boundaries:**
|
|
27
|
+
- **Input string (parse):** May come from untrusted sources (e.g., user input, network requests)
|
|
28
|
+
- **Input object (stringify):** May contain cycles, which can lead to infinite loops during stringification
|
|
29
|
+
- **Options:** Provided by the caller
|
|
30
|
+
- **Cycle Tracking:** Used only during stringification to detect and handle circular references
|
|
31
|
+
|
|
32
|
+
### 4. Identify Assets
|
|
33
|
+
|
|
34
|
+
- **Integrity of parsed output:** Prevent malicious manipulation of the output object structure, especially ensuring builtins/globals are not modified as a result of parse[3][4][8].
|
|
35
|
+
- **Confidentiality of processed data:** Avoid leaking sensitive information through errors or output.
|
|
36
|
+
- **Availability/performance for host application:** Prevent crashes or resource exhaustion in the consuming application.
|
|
37
|
+
- **Security of host application:** Prevent the library from being a vector for attacks (e.g., prototype pollution, DoS).
|
|
38
|
+
- **Reputation of library:** Maintain trust by avoiding supply chain attacks and vulnerabilities[1].
|
|
39
|
+
|
|
40
|
+
### 5. Identify Threats
|
|
41
|
+
|
|
42
|
+
| Component / API / Interaction | S | T | R | I | D | E |
|
|
43
|
+
|---------------------------------------|----|----|----|----|----|----|
|
|
44
|
+
| Public API Call (`parse`) | – | ✓ | – | ✓ | ✓ | ✓ |
|
|
45
|
+
| Public API Call (`stringify`) | – | ✓ | – | ✓ | ✓ | – |
|
|
46
|
+
| Options Handling | ✓ | ✓ | – | ✓ | – | ✓ |
|
|
47
|
+
| Dependency Interaction | – | – | – | – | ✓ | – |
|
|
48
|
+
|
|
49
|
+
**Key Threats:**
|
|
50
|
+
- **Tampering:** Malicious input can, if not prevented, alter parsed output (e.g., prototype pollution via `__proto__`, modification of builtins/globals)[3][4][8].
|
|
51
|
+
- **Information Disclosure:** Error messages may expose internal details or sensitive data.
|
|
52
|
+
- **Denial of Service:** Large or malformed input can exhaust memory or CPU.
|
|
53
|
+
- **Elevation of Privilege:** Prototype pollution can lead to unintended privilege escalation in the host application[3][4][8].
|
|
54
|
+
|
|
55
|
+
### 6. Mitigation/Countermeasures
|
|
56
|
+
|
|
57
|
+
| Threat Identified | Proposed Mitigation |
|
|
58
|
+
|---------------------------------------------------|---------------------|
|
|
59
|
+
| Tampering (malicious input, prototype pollution) | Strict input validation; keep `allowPrototypes: false` by default; use `plainObjects` for output; ensure builtins/globals are never modified by parse[4][8]. |
|
|
60
|
+
| Information Disclosure (error messages) | Generic error messages without stack traces or internal paths. |
|
|
61
|
+
| Denial of Service (memory/CPU exhaustion) | Enforce `arrayLimit` and `parameterLimit` with safe defaults; enable `throwOnLimitExceeded`; limit nesting depth[7]. |
|
|
62
|
+
| Elevation of Privilege (prototype pollution) | Keep `allowPrototypes: false`; validate options against allowlist; use `plainObjects` to avoid prototype pollution[4][8]. |
|
|
63
|
+
|
|
64
|
+
### 7. Risk Ranking
|
|
65
|
+
|
|
66
|
+
- **High:** Denial of Service via array parsing or malformed input (historical vulnerability)
|
|
67
|
+
- **Medium:** Prototype pollution via options or input (if `allowPrototypes` enabled)
|
|
68
|
+
- **Low:** Information disclosure in errors
|
|
69
|
+
|
|
70
|
+
### 8. Next Steps & Review
|
|
71
|
+
|
|
72
|
+
1. **Audit option validation logic.**
|
|
73
|
+
2. **Add depth limiting to nested parsing and stringification.**
|
|
74
|
+
3. **Implement fuzz testing for parser and stringifier edge cases.**
|
|
75
|
+
4. **Regularly review dependencies for vulnerabilities.**
|
|
76
|
+
5. **Keep documentation and threat model up to date.**
|
|
77
|
+
6. **Ensure builtins/globals are never modified as a result of parse.**
|
|
78
|
+
7. **Support round-trip consistency between parse and stringify as a non-security goal, with the right options[5][9].**
|
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
## **6.14.1**
|
|
2
|
+
- [Fix] ensure arrayLength applies to `[]` notation as well
|
|
3
|
+
- [Fix] `parse`: when a custom decoder returns `null` for a key, ignore that key
|
|
4
|
+
- [Refactor] `parse`: extract key segment splitting helper
|
|
5
|
+
- [meta] add threat model
|
|
6
|
+
- [actions] add workflow permissions
|
|
7
|
+
- [Tests] `stringify`: increase coverage
|
|
8
|
+
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `npmignore`, `es-value-fixtures`, `for-each`, `object-inspect`
|
|
9
|
+
|
|
10
|
+
## **6.14.0**
|
|
11
|
+
- [New] `parse`: add `throwOnParameterLimitExceeded` option (#517)
|
|
12
|
+
- [Refactor] `parse`: use `utils.combine` more
|
|
13
|
+
- [patch] `parse`: add explicit `throwOnLimitExceeded` default
|
|
14
|
+
- [actions] use shared action; re-add finishers
|
|
15
|
+
- [meta] Fix changelog formatting bug
|
|
16
|
+
- [Deps] update `side-channel`
|
|
17
|
+
- [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols`
|
|
18
|
+
- [Tests] increase coverage
|
|
19
|
+
|
|
20
|
+
## **6.13.1**
|
|
21
|
+
- [Fix] `stringify`: avoid a crash when a `filter` key is `null`
|
|
22
|
+
- [Fix] `utils.merge`: functions should not be stringified into keys
|
|
23
|
+
- [Fix] `parse`: avoid a crash with interpretNumericEntities: true, comma: true, and iso charset
|
|
24
|
+
- [Fix] `stringify`: ensure a non-string `filter` does not crash
|
|
25
|
+
- [Refactor] use `__proto__` syntax instead of `Object.create` for null objects
|
|
26
|
+
- [Refactor] misc cleanup
|
|
27
|
+
- [Tests] `utils.merge`: add some coverage
|
|
28
|
+
- [Tests] fix a test case
|
|
29
|
+
- [actions] split out node 10-20, and 20+
|
|
30
|
+
- [Dev Deps] update `es-value-fixtures`, `mock-property`, `object-inspect`, `tape`
|
|
31
|
+
|
|
1
32
|
## **6.13.0**
|
|
2
33
|
- [New] `parse`: add `strictDepth` option (#511)
|
|
3
34
|
- [Tests] use `npm audit` instead of `aud`
|
|
@@ -49,7 +49,7 @@ assert.deepEqual(qs.parse('foo[bar]=baz'), {
|
|
|
49
49
|
});
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
When using the `plainObjects` option the parsed value is returned as a null object, created via `
|
|
52
|
+
When using the `plainObjects` option the parsed value is returned as a null object, created via `{ __proto__: null }` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
|
|
53
53
|
|
|
54
54
|
```javascript
|
|
55
55
|
var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
|
|
@@ -135,6 +135,18 @@ var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
|
|
|
135
135
|
assert.deepEqual(limited, { a: 'b' });
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
+
If you want an error to be thrown whenever the a limit is exceeded (eg, `parameterLimit`, `arrayLimit`), set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
|
|
139
|
+
```javascript
|
|
140
|
+
try {
|
|
141
|
+
qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true });
|
|
142
|
+
} catch (err) {
|
|
143
|
+
assert(err instanceof Error);
|
|
144
|
+
assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.');
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
|
|
149
|
+
|
|
138
150
|
To bypass the leading question mark, use `ignoreQueryPrefix`:
|
|
139
151
|
|
|
140
152
|
```javascript
|
|
@@ -286,6 +298,18 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
|
|
|
286
298
|
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
|
|
287
299
|
```
|
|
288
300
|
|
|
301
|
+
If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
|
|
302
|
+
```javascript
|
|
303
|
+
try {
|
|
304
|
+
qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true });
|
|
305
|
+
} catch (err) {
|
|
306
|
+
assert(err instanceof Error);
|
|
307
|
+
assert.strictEqual(err.message, 'Array limit exceeded. Only 0 elements allowed in an array.');
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
|
|
312
|
+
|
|
289
313
|
To disable array parsing entirely, set `parseArrays` to `false`.
|
|
290
314
|
|
|
291
315
|
```javascript
|