Skip to content

Commit 1cd96fe

Browse files
authored
Use config file in addition to CLI parameters #12 (#31)
1 parent aacc10f commit 1cd96fe

16 files changed

+512
-84
lines changed

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
'windows-2022',
2222
'windows-latest',
2323
]
24-
node: [ '12', '14', '16', 'lts/*' ]
24+
node: [ '14', '16', 'lts/*' ]
2525
runs-on: ${{ matrix.runner }}
2626
name: ${{ matrix.runner }} runner with Node.js ${{ matrix.node }}
2727
steps:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Thumbs.db
88

99
# Tests
1010
/coverage/
11+
/tests/*.ignore
1112

1213
# Node / npm
1314
.npm

README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ See the [STAC Validator Comparison](COMPARISON.md) for the features supported by
1717

1818
## Quick Start
1919

20-
1. Install [node and npm](https://nodejs.org) - should run with any recent version
20+
1. Install a recent version of [node and npm](https://nodejs.org)
2121
2. `npx stac-node-validator /path/to/your/file-or-folder` to temporarily install the library and validate the provided file for folder. See the chapters below for advanced usage options.
2222

2323
## Setup
2424

25-
1. Install [node and npm](https://nodejs.org) - should run with any recent version
25+
1. Install [node and npm](https://nodejs.org) - should run with any version >= 14. Older versions may still work, but no guarantee.
2626
2. `npm install -g stac-node-validator` to install the library permanently
2727

2828
## Usage
@@ -46,6 +46,36 @@ Further options to add to the commands above:
4646
**Note on API support:** Validating lists of STAC items/collections (i.e. `GET /collections` and `GET /collections/:id/items`) is partially supported.
4747
It only checks the contained items/collections, but not the other parts of the response (e.g. `links`).
4848

49+
### Config file
50+
51+
You can also pass a config file via the `--config` option. Simply pass a file path as value.
52+
Parameters set via CLI will override the corresponding setting in the config file.
53+
Make sure to use the value `false` to override boolean flags that are set to `true` in the config file.
54+
55+
The config file uses the same option names as above.
56+
To specify the files to be validated, add an array with paths.
57+
The schema map is an object instead of string separated with a `=` character.
58+
59+
**Example:**
60+
```json
61+
{
62+
"files": [
63+
"/path/to/your/catalog.json",
64+
"/path/to/your/item.json"
65+
],
66+
"schemas": "/path/to/stac/folder",
67+
"schemaMap": {
68+
"https://stac-extensions.github.io/foobar/v1.0.0/schema.json": "./json-schema/schema.json"
69+
},
70+
"ignoreCerts": false,
71+
"verbose": false,
72+
"lint": true,
73+
"format": false
74+
}
75+
```
76+
77+
You could now override some options as follows in CLI: `stac-node-validator example.json --config /path/to/config.json --lint false`
78+
4979
### Development
5080

5181
1. `git clone https://github.com/stac-utils/stac-node-validator` to clone the repo

index.js

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let schemaFolder = null;
2626

2727
async function run(config) {
2828
try {
29-
let args = config || minimist(process.argv.slice(2), { boolean: ['verbose', 'ignoreCerts', 'lint', 'format', 'version'] });
29+
let args = config || minimist(process.argv.slice(2));
3030

3131
if (args.version) {
3232
console.log(version);
@@ -36,9 +36,38 @@ async function run(config) {
3636
console.log(`STAC Node Validator v${version}\n`);
3737
}
3838

39-
verbose = (typeof args.verbose !== 'undefined');
39+
// Read config from file
40+
if (typeof args.config === 'string') {
41+
let configFile;
42+
try {
43+
configFile = await fs.readFile(args.config, "utf8");
44+
} catch (error) {
45+
throw new Error('Config file does not exist.');
46+
}
47+
try {
48+
config = JSON.parse(configFile);
49+
} catch (error) {
50+
throw new Error('Config file is invalid JSON.');
51+
}
52+
}
4053

41-
let files = args._ || args.files || [];
54+
// Merge CLI parameters into config
55+
if (!config) {
56+
config = {};
57+
}
58+
for(let key in args) {
59+
let value = args[key];
60+
if (key === '_' && Array.isArray(value) && value.length > 0) {
61+
config.files = value;
62+
}
63+
else {
64+
config[key] = value;
65+
}
66+
}
67+
68+
verbose = Boolean(config.verbose);
69+
70+
let files = Array.isArray(config.files) ? config.files : [];
4271
if (files.length === 0) {
4372
throw new Error('No path or URL specified.');
4473
}
@@ -50,42 +79,45 @@ async function run(config) {
5079
}
5180
}
5281

53-
if (typeof args.ignoreCerts !== 'undefined') {
82+
if (config.ignoreCerts) {
5483
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
5584
}
5685

57-
if (typeof args.schemas === 'string') {
58-
let stat = await fs.lstat(args.schemas);
86+
if (typeof config.schemas === 'string') {
87+
let stat = await fs.lstat(config.schemas);
5988
if (stat.isDirectory()) {
60-
schemaFolder = normalizePath(args.schemas);
89+
schemaFolder = normalizePath(config.schemas);
6190
}
6291
else {
6392
throw new Error('Schema folder is not a valid STAC directory');
6493
}
6594
}
6695

6796
let schemaMapArgs = [];
68-
if (Array.isArray(args.schemaMap)) {
97+
if (config.schemaMap && typeof config.schemaMap === 'object') {
6998
// Recommended way
70-
schemaMapArgs = args.schemaMap;
99+
schemaMapArgs = config.schemaMap;
71100
}
72-
else if (typeof args.schemaMap === 'string') {
101+
else if (typeof config.schemaMap === 'string') {
73102
// Backward compliance
74-
schemaMapArgs = args.schemaMap.split(';');
103+
schemaMapArgs = config.schemaMap.split(';');
75104
}
76-
for(let arg of schemaMapArgs) {
77-
let parts = arg.split("=");
78-
let stat = await fs.lstat(parts[1]);
105+
for(let url in schemaMapArgs) {
106+
let path = schemaMapArgs[url];
107+
if (typeof url === 'string') { // from CLI
108+
[url, path] = path.split("=");
109+
}
110+
let stat = await fs.lstat(path);
79111
if (stat.isFile()) {
80-
schemaMap[parts[0]] = parts[1];
112+
schemaMap[url] = path;
81113
}
82114
else {
83-
console.error(`Schema mapping for ${parts[0]} is not a valid file: ${normalizePath(parts[1])}`);
115+
console.error(`Schema mapping for ${url} is not a valid file: ${normalizePath(path)}`);
84116
}
85117
}
86118

87-
const doLint = (typeof args.lint !== 'undefined');
88-
const doFormat = (typeof args.format !== 'undefined');
119+
const doLint = Boolean(config.lint);
120+
const doFormat = Boolean(config.format);
89121

90122
let stats = {
91123
files: files.length,
@@ -236,7 +268,7 @@ async function run(config) {
236268
fileValid = false;
237269
if (core && !DEBUG) {
238270
if (verbose) {
239-
console.info("-- Validation error in core, skipping extension validation");
271+
console.warn("-- Validation error in core, skipping extension validation");
240272
}
241273
break;
242274
}

jest.config.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ module.exports = {
4444
// An object that configures minimum threshold enforcement for coverage results
4545
"coverageThreshold": {
4646
"global": {
47-
"branches": 65,
48-
"functions": 81,
49-
"lines": 69
47+
"statements": 80,
48+
"branches": 75,
49+
"functions": 100,
50+
"lines": 80
5051
}
5152
}
5253

tests/api/collections.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"collections": [
3+
{
4+
"id": "simple-collection",
5+
"type": "Collection",
6+
"stac_extensions": [
7+
"https://stac-extensions.github.io/eo/v1.0.0/schema.json",
8+
"https://stac-extensions.github.io/projection/v1.0.0/schema.json",
9+
"https://stac-extensions.github.io/view/v1.0.0/schema.json"
10+
],
11+
"stac_version": "1.0.0",
12+
"description": "A simple collection demonstrating core catalog fields with links to a couple of items",
13+
"title": "Simple Example Collection",
14+
"providers": [
15+
{
16+
"name": "Remote Data, Inc",
17+
"description": "Producers of awesome spatiotemporal assets",
18+
"roles": [
19+
"producer",
20+
"processor"
21+
],
22+
"url": "http://remotedata.io"
23+
}
24+
],
25+
"extent": {
26+
"spatial": {
27+
"bbox": [
28+
[
29+
172.91173669923782,
30+
1.3438851951615003,
31+
172.95469614953714,
32+
1.3690476620161975
33+
]
34+
]
35+
},
36+
"temporal": {
37+
"interval": [
38+
[
39+
"2020-12-11T22:38:32.125Z",
40+
"2020-12-14T18:02:31.437Z"
41+
]
42+
]
43+
}
44+
},
45+
"license": "CC-BY-4.0",
46+
"summaries": {
47+
"platform": [
48+
"cool_sat1",
49+
"cool_sat2"
50+
],
51+
"constellation": [
52+
"ion"
53+
],
54+
"instruments": [
55+
"cool_sensor_v1",
56+
"cool_sensor_v2"
57+
]
58+
},
59+
"links": [
60+
{
61+
"rel": "root",
62+
"href": "./collection.json",
63+
"type": "application/json",
64+
"title": "Simple Example Collection"
65+
},
66+
{
67+
"rel": "item",
68+
"href": "./simple-item.json",
69+
"type": "application/geo+json",
70+
"title": "Simple Item"
71+
},
72+
{
73+
"rel": "self",
74+
"href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0/examples/collection.json",
75+
"type": "application/json"
76+
}
77+
]
78+
}
79+
],
80+
"links": []
81+
}

tests/api/items.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"features": [
3+
{
4+
"stac_version": "1.0.0",
5+
"stac_extensions": [],
6+
"type": "Feature",
7+
"id": "20201211_223832_CS2",
8+
"bbox": [
9+
172.91173669923782,
10+
1.3438851951615003,
11+
172.95469614953714,
12+
1.3690476620161975
13+
],
14+
"geometry": {
15+
"type": "Polygon",
16+
"coordinates": [
17+
[
18+
[
19+
172.91173669923782,
20+
1.3438851951615003
21+
],
22+
[
23+
172.95469614953714,
24+
1.3438851951615003
25+
],
26+
[
27+
172.95469614953714,
28+
1.3690476620161975
29+
],
30+
[
31+
172.91173669923782,
32+
1.3690476620161975
33+
],
34+
[
35+
172.91173669923782,
36+
1.3438851951615003
37+
]
38+
]
39+
]
40+
},
41+
"properties": {
42+
"datetime": "2020-12-11T22:38:32.125000Z"
43+
},
44+
"links": [
45+
{
46+
"rel": "root",
47+
"href": "./collection.json",
48+
"type": "application/json",
49+
"title": "Simple Example Collection"
50+
},
51+
{
52+
"rel": "parent",
53+
"href": "./collection.json",
54+
"type": "application/json",
55+
"title": "Simple Example Collection"
56+
}
57+
],
58+
"assets": {
59+
"visual": {
60+
"href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif",
61+
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
62+
"title": "3-Band Visual",
63+
"roles": [
64+
"visual"
65+
]
66+
}
67+
}
68+
},{
69+
"stac_version": "1.0.0",
70+
"type": "Feature",
71+
"id": "invalid",
72+
"bbox": null,
73+
"geometry": null,
74+
"properties": {
75+
"datetime": "2020-12-11T22:38:32.125000Z"
76+
},
77+
"links": [],
78+
"assets": {}
79+
}
80+
81+
],
82+
"links": []
83+
}

tests/catalog-with-invalid-schema.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/catalog.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)