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

stac-js

Package Overview
Dependencies
Maintainers
0
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stac-js - npm Package Compare versions

Comparing version 0.0.9 to 0.1.0

src/band.js

17

package.json
{
"name": "stac-js",
"version": "0.0.9",
"version": "0.1.0",
"description": "JS drop-in classes with utilities for STAC",

@@ -18,2 +18,6 @@ "author": "Matthias Mohr",

},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/m-mohr"
},
"type": "module",

@@ -27,3 +31,3 @@ "main": "src/index.js",

"docs_lint": "npx documentation lint src/**",
"lint": "eslint \"./src/**/*.js\" -c .eslintrc.json",
"lint": "eslint \"./src/**/*.js\" -c eslint.config.mjs",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",

@@ -33,4 +37,7 @@ "check": "npm run docs_lint && npm run lint && npm test"

"devDependencies": {
"eslint": "^8.34.0",
"eslint-plugin-jsdoc": "^40.0.0",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.18.0",
"eslint": "^9.18.0",
"eslint-plugin-jsdoc": "^50.0.0",
"globals": "^15.14.0",
"jest": "^29.0.0",

@@ -40,5 +47,5 @@ "jest-html-reporter": "^3.3.0"

"dependencies": {
"@radiantearth/stac-migrate": "^1.5.0",
"@radiantearth/stac-migrate": "^2.0.1",
"urijs": "^1.19.11"
}
}

@@ -9,3 +9,3 @@ # stac-js

- **Package version:** 0.0.9
- **Package version:** 0.1.0
- **STAC versions:** >= 0.6.0 (through [stac-migrate](https://github.com/stac-utils/stac-migrate)).

@@ -17,2 +17,3 @@ - **Documentation:** <https://m-mohr.github.io/stac-js/latest/>

Automatically instantiate the right class through the factory:
```js

@@ -23,3 +24,3 @@ import create from 'stac-js';

const stac = {
stac_version: "1.0.0",
stac_version: "1.1.0",
type: "Collection",

@@ -33,2 +34,3 @@ id: "example",

Directly instantiate `Asset`, `Catalog`, `Collection`, `CollectionCollection`, `Item` or `ItemCollection` through the class constructors:
```js

@@ -39,3 +41,3 @@ import { Collection } from 'stac-js'; // or Catalog or Item

const stac = {
stac_version: "1.0.0",
stac_version: "1.1.0",
type: "Collection",

@@ -49,2 +51,3 @@ id: "example",

You can then use the object, check whether it's STAC and call some methods, for example:
```js

@@ -66,2 +69,3 @@ import { STAC } from 'stac-js';

The classes are drop-in replacements, which means you can still access the objects as before:
```js

@@ -68,0 +72,0 @@ console.log(stac.id === obj.id);

@@ -1,4 +0,14 @@

import { getMaxForDataType, getMinForDataType, hasText, isObject, mergeArraysOfObjects } from "./utils.js";
import { getMinMaxValues, getNoDataValues, hasText, isObject } from "./utils.js";
import STACReference from './reference.js';
import Band from "./band.js";
const NO_INHERITANCE = [
'created',
'updated',
'published',
'expires',
'unpublished',
'bands'
];
/**

@@ -23,3 +33,3 @@ * A STAC Asset or Item Asset Definition.

constructor(data, key = null, context = null) {
super(data, context, {}, ['_key']);
super(data, context, { bands: Band.fromBands }, ['_key']);
if (!this._key) {

@@ -83,3 +93,3 @@ this._key = key;

}
if (this._context) {
if (this._context && !NO_INHERITANCE.includes(field)) {
return this._context.getMetadata(field);

@@ -93,8 +103,6 @@ }

*
* This is usually a merge of eo:bands and raster:bands.
*
* @returns {Array.<Object>}
* @returns {Array.<Band>}
*/
getBands() {
return mergeArraysOfObjects(this['eo:bands'], this['raster:bands']);
return this.bands || [];
}

@@ -106,5 +114,5 @@

* @typedef {Object} VisualBands
* @property {BandWithIndex} red The red band with its index
* @property {BandWithIndex} green The green band with its index
* @property {BandWithIndex} blue The blue band with its index
* @property {Band} red The red band with its index
* @property {Band} green The green band with its index
* @property {Band} blue The blue band with its index
*/

@@ -118,3 +126,3 @@

findVisualBands() {
let rgb = {
const rgb = {
red: null,

@@ -124,11 +132,11 @@ green: null,

};
let bands = this.getBands();
for(let key in bands) {
let index = parseInt(key, 10); // findIndex returns number, for loop uses strings?!
let band = bands[index];
if (isObject(band) && hasText(band.common_name) && band.common_name in rgb) {
rgb[band.common_name] = { index, band };
const bands = this.getBands();
for(const key in bands) {
const index = parseInt(key, 10); // for loop may return strings as keys
const band = bands[index];
if (isObject(band) && hasText(band['eo:common_name']) && band['eo:common_name'] in rgb) {
rgb[band['eo:common_name']] = band;
}
}
let complete = Object.values(rgb).every(o => o !== null);
const complete = Object.values(rgb).every(o => o !== null);
return complete ? rgb : null;

@@ -144,16 +152,13 @@ }

* @param {string} property The property in the bands to match against.
* @param {Array.<Object>} bands For performance reasons you can provide a list of merged bands from `getBands()`.
* @returns {BandWithIndex|null}
* @returns {Band|null}
* @see {getBands}
*/
findBand(value, property = 'name', bands = null) {
findBand(value, property = 'name') {
if (!Array.isArray(value)) {
value = [value];
}
if (!isObject(bands)) {
bands = this.getBands();
}
let index = bands.findIndex(band => isObject(band) && value.includes(band[property]));
const bands = this.getBands();
const index = bands.findIndex(band => isObject(band) && value.includes(band[property]));
if (index >= 0) {
return { index, band: bands[index] };
return bands[index];
}

@@ -176,3 +181,3 @@ return null;

}
let bands = this.getBands();
const bands = this.getBands();
return bands[band] || null;

@@ -182,131 +187,21 @@ }

/**
* Gets the reported minimum and maximum values for an asset (or band).
* Gets the reported minimum and maximum values for an asset.
*
* Searches through different extension fields in raster, claasification, and file.
*
* @param {Object|number} band
* @returns {Statistics}
*/
getMinMaxValues(band = null) {
band = this.getBand(band);
/**
* Statistics
*
* @typedef {Object} Statistics
* @property {number|null} minimum Minimum value
* @property {number|null} maximum Maximum value
*/
const stats = {
minimum: null,
maximum: null
};
// Checks whether the stats object is completely filled
const isComplete = obj => obj.minimum !== null && obj.maximum !== null;
// data sources: raster (statistics, histogram, data_type), classification, file (values, data_type)
if (band) {
if (isObject(band.statistics)) {
if (typeof band.statistics.minimum === 'number') {
stats.minimum = band.statistics.minimum;
}
if (typeof band.statistics.maximum === 'number') {
stats.maximum = band.statistics.maximum;
}
if (isComplete(stats)) {
return stats;
}
}
if (isObject(band.histogram)) {
if (typeof band.histogram.min === 'number') {
stats.minimum = band.histogram.min;
}
if (typeof band.histogram.max === 'number') {
stats.maximum = band.histogram.max;
}
if (isComplete(stats)) {
return stats;
}
}
}
let classification = this.getMetadata("classification:classes");
if (Array.isArray(classification)) {
classification.reduce((obj, cls) => {
obj.minimum = Math.min(obj.minimum, cls.value);
obj.maximum = Math.max(obj.maximum, cls.value);
return obj;
}, stats);
if (isComplete(stats)) {
return stats;
}
}
let values = this.getMetadata("file:values");
if (Array.isArray(values)) {
values.reduce((obj, map) => {
obj.minimum = Math.min(obj.minimum, ...map.values);
obj.maximum = Math.max(obj.maximum, ...map.values);
return obj;
}, stats);
if (isComplete(stats)) {
return stats;
}
}
let data_type = (isObject(band) && band.data_type) || this.getMetadata("file:data_type");
if (data_type) {
stats.minimum = getMinForDataType(data_type);
stats.maximum = getMaxForDataType(data_type);
}
return stats;
getMinMaxValues() {
return getMinMaxValues(this);
}
/**
* Gets the reported no-data values for an asset (or band).
* Gets the reported no-data values for an asset.
*
* Searches through different extension fields in raster, claasification, and file.
* Searches through different extension fields in nodata, classification, and file.
*
* @param {Object|number} band
* @returns {Array.<*>}
*/
getNoDataValues(band = null) {
band = this.getBand(band);
// data sources: raster (nodata), classification (nodata flag), file (nodata)
let nodata = [];
if (band && typeof band.nodata !== 'undefined') {
nodata.push(band.nodata);
}
else {
let file = this.getMetadata("file:nodata");
if (typeof file !== 'undefined') {
nodata = file;
}
else {
let classification = this.getMetadata("classification:classes");
if (Array.isArray(classification)) {
nodata = classification
.filter(cls => Boolean(cls.nodata))
.map(cls => cls.value);
}
}
}
return nodata.map(value => {
if (value === "nan") {
return NaN;
}
else if (value === "+inf") {
return +Infinity;
}
else if (value === "-inf") {
return -Infinity;
}
else {
return value;
}
});
getNoDataValues() {
return getNoDataValues(this);
}

@@ -313,0 +208,0 @@

import Asset from './asset.js';
import Band from './band.js';
import CatalogLike from './cataloglike.js';
import { isoToDate } from './datetime.js';
import { isBoundingBox, toGeoJSON } from './geo.js';
import { hasText, mergeArraysOfObjects } from './utils.js';
import { hasText } from './utils.js';

@@ -155,19 +156,13 @@ /**

*
* This is usually a merge of eo:bands and raster:bands from the summaries.
*
* @returns {Array.<Object>}
* @returns {Array.<Band>}
*/
getBands() {
let eo = this.getSummary('eo:bands');
let raster = this.getSummary('raster:bands');
let all = [eo, raster].filter(arr => Array.isArray(arr));
if (all.length >= 2) {
return mergeArraysOfObjects(...all);
let bands = this.getMetadata('bands');
if (!Array.isArray(bands)) {
bands = this.getSummary('bands');
}
else if (all.length === 1) {
return all[0];
}
else {
if (!Array.isArray(bands)) {
return [];
}
return Band.fromBands(bands, this);
}

@@ -174,0 +169,0 @@

@@ -16,3 +16,3 @@ import { hasText } from "./utils.js";

return new Date(Date.UTC(dt[0], dt[1] - 1, dt[2], dt[3], dt[4], dt[5], dt[6] || 0));
} catch(error) {
} catch {
return null;

@@ -19,0 +19,0 @@ }

@@ -6,2 +6,3 @@ import Asset from './asset.js';

import STAC from './stac.js';
import Band from './band.js';

@@ -138,11 +139,10 @@ /**

* @todo Merge bands from assets
* @returns {Array.<Object>}
* @returns {Array.<Band>}
*/
getBands() {
let eo = this.getMetadata('eo:bands');
if (Array.isArray(eo)) {
return eo;
const bands = this.getMetadata('bands');
if (Array.isArray(bands)) {
return Band.fromBands(bands, this);
}
else {
// todo: merge bands from assets?
return [];

@@ -149,0 +149,0 @@ }

@@ -110,3 +110,3 @@ import { centerOfBoundingBox } from './geo.js';

/**
* Check whether this given object is a STAC LInk.
* Check whether this given object is a STAC Link.
*

@@ -120,2 +120,11 @@ * @returns {boolean} `true` if the object is a STAC Link, `false` otherwise.

/**
* Check whether this given object is a STAC Band.
*
* @returns {boolean} `true` if the object is a STAC Band, `false` otherwise.
*/
isBand() {
return false;
}
/**
* Returns the type of the STAC object.

@@ -131,2 +140,3 @@ *

* - Link
* - Band
* @abstract

@@ -133,0 +143,0 @@ * @returns {string}

@@ -18,3 +18,3 @@ import { browserProtocols, toAbsolute } from './http.js';

* @param {Object} data The STAC API Collection object
* @param {STAC|null} context The object that contains the link
* @param {STAC|null} context The object that contains the reference
* @param {Object.<string, function>} keyMap Keys and functions that convert the values to stac-js objects.

@@ -21,0 +21,0 @@ * @param {Array.<string>} privateKeys Keys that are private members of the stac-js objects (for cloning and export).

@@ -177,5 +177,5 @@ import { geotiffMediaTypes, isMediaType } from './mediatypes.js';

* @typedef {Object} VisualAssets
* @property {BandWithIndex} red The red band with its index
* @property {BandWithIndex} green The green band with its index
* @property {BandWithIndex} blue The blue band with its index
* @property {Band} red The red band with its index
* @property {Band} green The green band with its index
* @property {Band} blue The blue band with its index
*/

@@ -197,9 +197,5 @@

for(let asset of assets) {
let bands = asset.getBands();
if (bands.length !== 1) {
continue;
}
let result = asset.findBand(names, 'common_name', bands);
let result = asset.findBand(names, 'eo:common_name');
if (result) {
rgb[result.band.common_name] = asset;
rgb[result["eo:common_name"]] = asset;
}

@@ -206,0 +202,0 @@ }

@@ -14,10 +14,2 @@ /**

/**
* A band with the corresponding index.
*
* @typedef {Object} BandWithIndex
* @property {number} index The index in the bands array.
* @property {Object} band The band object
*/
/**
* A data provider.

@@ -24,0 +16,0 @@ *

@@ -98,1 +98,132 @@ /**

}
/**
* Gets the reported minimum and maximum values for a STAC object.
*
* Searches through different extension fields in raster, claasification, and file.
*
* @param {StacObject} object
* @returns {Statistics}
*/
export function getMinMaxValues(object) {
/**
* Statistics
*
* @typedef {Object} Statistics
* @property {number|null} minimum Minimum value
* @property {number|null} maximum Maximum value
*/
const stats = {
minimum: null,
maximum: null
};
// Checks whether the stats object is completely filled
const isComplete = obj => obj.minimum !== null && obj.maximum !== null;
// data sources: raster (statistics, histogram, data_type), classification, file (values, data_type)
const statistics = object.getMetadata("statistics");
if (isObject(statistics)) {
if (typeof statistics.minimum === 'number') {
stats.minimum = statistics.minimum;
}
if (typeof statistics.maximum === 'number') {
stats.maximum = statistics.maximum;
}
if (isComplete(stats)) {
return stats;
}
}
const histogram = object.getMetadata("raster:histogram");
if (isObject(histogram)) {
if (typeof histogram.min === 'number') {
stats.minimum = histogram.min;
}
if (typeof histogram.max === 'number') {
stats.maximum = histogram.max;
}
if (isComplete(stats)) {
return stats;
}
}
const classification = object.getMetadata("classification:classes");
if (Array.isArray(classification)) {
classification.reduce((obj, cls) => {
obj.minimum = Math.min(obj.minimum, cls.value);
obj.maximum = Math.max(obj.maximum, cls.value);
return obj;
}, stats);
if (isComplete(stats)) {
return stats;
}
}
const values = object.getMetadata("file:values");
if (Array.isArray(values)) {
values.reduce((obj, map) => {
obj.minimum = Math.min(obj.minimum, ...map.values);
obj.maximum = Math.max(obj.maximum, ...map.values);
return obj;
}, stats);
if (isComplete(stats)) {
return stats;
}
}
const data_type = object.getMetadata("data_type");
if (data_type) {
stats.minimum = getMinForDataType(data_type);
stats.maximum = getMaxForDataType(data_type);
}
return stats;
}
/**
* Gets the reported no-data values for a STAC Object.
*
* Searches through different extension fields in nodata, classification, and file.
*
* @param {StacObject} object
* @returns {Array.<*>}
*/
export function getNoDataValues(object) {
// data sources: raster (nodata), classification (nodata flag), file (nodata)
let nodata = [];
const common = object.getMetadata("nodata");
if (typeof common !== 'undefined') {
nodata.push(common);
}
else {
const file = object.getMetadata("file:nodata");
if (typeof file !== 'undefined') {
nodata = file;
}
else {
const classification = object.getMetadata("classification:classes");
if (Array.isArray(classification)) {
nodata = classification
.filter(cls => Boolean(cls.nodata))
.map(cls => cls.value);
}
}
}
return nodata.map(value => {
if (value === "nan") {
return NaN;
}
else if (value === "+inf") {
return +Infinity;
}
else if (value === "-inf") {
return -Infinity;
}
else {
return value;
}
});
}
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