From 7ec14b16cd23af34c9c82e8cd17beae0b1945a7a Mon Sep 17 00:00:00 2001 From: ingalls Date: Thu, 1 Dec 2022 09:54:47 -0700 Subject: [PATCH 01/24] Include pypgstac database tool in base image --- services/api/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/api/Dockerfile b/services/api/Dockerfile index 717312ae..11797dce 100644 --- a/services/api/Dockerfile +++ b/services/api/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.17 -RUN apk add --no-cache bash nodejs npm +RUN apk add --no-cache bash nodejs npm python3 py3-pip EXPOSE 2000 @@ -9,6 +9,8 @@ WORKDIR $HOME COPY ./ $HOME/api WORKDIR $HOME/api +RUN pip install pypgstac[psycopg] + RUN npm install \ && npm run doc From 4cd93ce30464e96d1ba50f300e4f4327af352bb4 Mon Sep 17 00:00:00 2001 From: ingalls Date: Thu, 1 Dec 2022 10:14:33 -0700 Subject: [PATCH 02/24] Setup Database migration tool with pgstac --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4db52631..4b24a1e3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -63,7 +63,7 @@ services: migration: platform: linux/amd64 build: ./services/api - command: sh -c "sleep 20; npx knex migrate:latest" + command: sh -c "pgstac --dsn $Postgres pgready && npx knex migrate:latest && pgstac --dsn $Postgres migrate" links: - postgis ports: From 0458cfcd340d343c7e37b2765fb5218c825392f7 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 07:47:41 -0700 Subject: [PATCH 03/24] Sketch out stac docker --- docker-compose.yml | 14 +++++++++ package-lock.json | 72 +++++++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4b24a1e3..fe96cc92 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,20 @@ services: - Postgres=postgres://docker:docker@postgis:5432/gis - AZURE_STORAGE_CONNECTION_STRING + stac: + platform: linux/amd64 + build: ./services/stac/ + command: sh -c "sleep 5; npm run dev" + restart: always + links: + - postgis + depends_on: + - migration + ports: + - "2001:2001" + environment: + - Postgres=postgres://docker:docker@postgis:5432/gis + postgis: platform: linux/amd64 image: kartoza/postgis:13.0 diff --git a/package-lock.json b/package-lock.json index 7ff06e7a..b43bee2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -209,9 +209,9 @@ } }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "18.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", + "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" }, "node_modules/@typescript-plus/fast-memoize-decorator": { "version": "0.1.0", @@ -272,9 +272,9 @@ } }, "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.2.0.tgz", - "integrity": "sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.3.0.tgz", + "integrity": "sha512-gezeeOIZyQLGW5uuCeEnXF1aXmtt2afKspXz3YqoOcZ3l/YMJq1pujvgT+cz/Nw1O/7q/kSav5fihJHsC/AOUg==", "engines": { "node": ">=14.16" }, @@ -967,9 +967,9 @@ } }, "node_modules/eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.3.3", @@ -1352,9 +1352,9 @@ "peer": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1844,9 +1844,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true, "engines": { "node": ">= 4" @@ -3501,9 +3501,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.6.0.tgz", + "integrity": "sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ==", "dependencies": { "tslib": "^2.1.0" } @@ -4544,9 +4544,9 @@ } }, "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "18.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", + "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" }, "@typescript-plus/fast-memoize-decorator": { "version": "0.1.0", @@ -4589,9 +4589,9 @@ }, "dependencies": { "type-fest": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.2.0.tgz", - "integrity": "sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.3.0.tgz", + "integrity": "sha512-gezeeOIZyQLGW5uuCeEnXF1aXmtt2afKspXz3YqoOcZ3l/YMJq1pujvgT+cz/Nw1O/7q/kSav5fihJHsC/AOUg==" } } }, @@ -5106,9 +5106,9 @@ "dev": true }, "eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dev": true, "requires": { "@eslint/eslintrc": "^1.3.3", @@ -5400,9 +5400,9 @@ "peer": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -5755,9 +5755,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true }, "import-fresh": { @@ -6922,9 +6922,9 @@ } }, "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.6.0.tgz", + "integrity": "sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ==", "requires": { "tslib": "^2.1.0" } From ca2244f329e927bfcf32bd268e1e629e8cf34697 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 07:50:02 -0700 Subject: [PATCH 04/24] FastAPI Stac --- services/stac/Dockerfile | 15 +++++++++++++++ services/stac/requirements.txt | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 services/stac/Dockerfile create mode 100644 services/stac/requirements.txt diff --git a/services/stac/Dockerfile b/services/stac/Dockerfile new file mode 100644 index 00000000..bf68aeab --- /dev/null +++ b/services/stac/Dockerfile @@ -0,0 +1,15 @@ +FROM alpine:3.17 + +RUN apk add --no-cache bash nodejs npm python3 py3-pip + +EXPOSE 2000 + +ENV HOME=/home/lulc +WORKDIR $HOME +COPY ./ $HOME/stac +WORKDIR $HOME/stac + +RUN pip install -r requirements.txt + + + diff --git a/services/stac/requirements.txt b/services/stac/requirements.txt new file mode 100644 index 00000000..16b18df9 --- /dev/null +++ b/services/stac/requirements.txt @@ -0,0 +1,5 @@ +stac-fastapi.api==2.4.3 +stac-fastapi.types==2.4.3 +stac-fastapi.extensions==2.4.3 +stac-fastapi.pgstac==2.4.3 + From 462f65720c05c4c7b3d76ffb1d1b98d33ef74a8a Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 10:29:27 -0700 Subject: [PATCH 05/24] Continue sketching out Dockerfile for STAC API --- services/stac/Dockerfile | 11 +++++++---- services/stac/pyproject.toml | 19 +++++++++++++++++++ services/stac/requirements.txt | 5 ----- services/stac/start.sh | 8 ++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 services/stac/pyproject.toml delete mode 100644 services/stac/requirements.txt create mode 100755 services/stac/start.sh diff --git a/services/stac/Dockerfile b/services/stac/Dockerfile index bf68aeab..49d443f3 100644 --- a/services/stac/Dockerfile +++ b/services/stac/Dockerfile @@ -1,15 +1,18 @@ FROM alpine:3.17 -RUN apk add --no-cache bash nodejs npm python3 py3-pip - -EXPOSE 2000 +EXPOSE 2001 ENV HOME=/home/lulc WORKDIR $HOME COPY ./ $HOME/stac WORKDIR $HOME/stac -RUN pip install -r requirements.txt +COPY ./api . + +RUN apk add --no-cache bash nodejs npm python3 py3-pip +RUN pip install -U pip +RUN python -m pip install . --no-cache-dir +CMD ["bash", "start.sh"] diff --git a/services/stac/pyproject.toml b/services/stac/pyproject.toml new file mode 100644 index 00000000..85cf78b1 --- /dev/null +++ b/services/stac/pyproject.toml @@ -0,0 +1,19 @@ +[project] +name = "pearl-backend-stac" +description = "Pearl STAC Backend" +requires-python = ">=3.7" +dynamic = ["version"] +dependencies = [ + "stac-fastapi.api==2.4.3", + "stac-fastapi.extensions==2.4.3", + "stac-fastapi.pgstac==2.4.3", + "stac-fastapi.types==2.4.3", + + "uvicorn", + + "requests", + "itsdangerous", + "pypgstac==0.6.10", + "psycopg==3.0.14", + "psycopg_pool== 3.1.1", +] diff --git a/services/stac/requirements.txt b/services/stac/requirements.txt deleted file mode 100644 index 16b18df9..00000000 --- a/services/stac/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -stac-fastapi.api==2.4.3 -stac-fastapi.types==2.4.3 -stac-fastapi.extensions==2.4.3 -stac-fastapi.pgstac==2.4.3 - diff --git a/services/stac/start.sh b/services/stac/start.sh new file mode 100755 index 00000000..59d196b4 --- /dev/null +++ b/services/stac/start.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo 'Run migrations if not already run' +pypgstac migrate --dsn $DATABASE_URL + +psql $DATABASE_URL -f $(pwd)/mc_ricr_api/dbfuncs.sql + +uvicorn mc_ricr_api.app:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' From 62dc2df36ec88f749d03c2ea5741040bffef39fa Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 10:37:32 -0700 Subject: [PATCH 06/24] Add __init__ --- services/stac/api/__init__.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 services/stac/api/__init__.py diff --git a/services/stac/api/__init__.py b/services/stac/api/__init__.py new file mode 100644 index 00000000..09146c02 --- /dev/null +++ b/services/stac/api/__init__.py @@ -0,0 +1,3 @@ +"""Pearl Backend Stac API.""" + +__version__ = "0.1.0" From e4e1de5d875ff19fe9f6c44d77dd7941aa92d9f8 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 10:42:50 -0700 Subject: [PATCH 07/24] Add Prelim API --- services/stac/api/app.py | 171 ++++++++++++++++++++++++++++++++++ services/stac/api/settings.py | 40 ++++++++ 2 files changed, 211 insertions(+) create mode 100644 services/stac/api/app.py create mode 100644 services/stac/api/settings.py diff --git a/services/stac/api/app.py b/services/stac/api/app.py new file mode 100644 index 00000000..da1c0d21 --- /dev/null +++ b/services/stac/api/app.py @@ -0,0 +1,171 @@ +import json +import logging +import pathlib +from datetime import datetime, timedelta +from typing import Optional +from urllib.parse import parse_qs, urlencode, urlparse, urlunparse + +import requests +from fastapi import Depends, FastAPI, Request +from fastapi.middleware.cors import CORSMiddleware + +from stac_fastapi.api.app import StacApi +from stac_fastapi.api.models import create_get_request_model, create_post_request_model +from stac_fastapi.extensions.core import ( + ContextExtension, + FieldsExtension, + FilterExtension, + SortExtension, + TokenPaginationExtension, + TransactionExtension, +) +from stac_fastapi.pgstac.config import Settings as STACSettings +from stac_fastapi.pgstac.core import CoreCrudClient +from stac_fastapi.pgstac.db import close_db_connection as stac_closedb +from stac_fastapi.pgstac.db import connect_to_db as stac_connectdb +from stac_fastapi.pgstac.extensions import QueryExtension +from stac_fastapi.pgstac.transactions import TransactionsClient +from stac_fastapi.pgstac.types.search import PgstacSearch +from starlette.middleware.base import BaseHTTPMiddleware +from starlette_cramjam.middleware import CompressionMiddleware + +from app.settings import Settings as AppSettings + + +# Boiler Plate for Stac FastApi PGStac +class Settings(STACSettings, AppSettings): + ... + + +settings = Settings() + +extensions = [ + TransactionExtension( + client=TransactionsClient(), + settings=settings, + response_class=ORJSONResponse, + ), + QueryExtension(), + SortExtension(), + FieldsExtension(), + TokenPaginationExtension(), + ContextExtension(), + FilterExtension(), +] + +post_request_model = create_post_request_model(extensions, base_model=PgstacSearch) +# End Stac FastAPI Boiler Plate + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +class StacRouteFixMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request, call_next): + base_url = settings.ricr_base_url or request.base_url._url + url = urlparse(base_url) + request.scope["scheme"] = url.scheme + if request.url.path.startswith("/stac/"): + request.scope["root_path"] = "/stac" + response = await call_next(request) + return response + +app = FastAPI( + title="Pearl Backend STAC", + version="0.0.1", + debug=settings.debug, +) +app.state.settings = settings +app.state.router_prefix = "" + + +app.add_middleware(StacRouteFixMiddleware) + +app.add_middleware( + CORSMiddleware, + allow_origins=settings.cors_origins, + allow_credentials=True, + allow_methods=["GET", "POST", "OPTIONS"], + allow_headers=["*"], +) + +app.add_middleware(CompressionMiddleware) + +stac = StacApi( + settings=settings, + extensions=extensions, + client=CoreCrudClient(post_request_model=post_request_model), + response_class=ORJSONResponse, + search_get_request_model=create_get_request_model(extensions), + search_post_request_model=post_request_model, +) +app.include_router( + stac.router, + dependencies=[Depends(authenticated)], + prefix="/stac", + tags=["STAC"], +) + +""" + Setup API doc over-rides for individual endpoints +""" + + +def custom_openapi(): + """ + Read JSON files from folder with over-rides for summaries and descriptions for specific paths and + over-write the same in the OpenAPI schema. + """ + if app.openapi_schema: + return app.openapi_schema + openapi_schema = app.openapi() + for f in TAGS_JSON_FILES: + with f.open() as tags: + endpoints = json.load(tags) + for endpoint in endpoints: + if ( + endpoint["path"] not in openapi_schema["paths"] + or endpoint["method"] not in openapi_schema["paths"][endpoint["path"]] + ): + logger.warn(f"Endpoint not configured correctly for {endpoint['path']}") + continue + openapi_schema["paths"][endpoint["path"]][endpoint["method"]][ + "summary" + ] = endpoint["summary"] + openapi_schema["paths"][endpoint["path"]][endpoint["method"]][ + "description" + ] = endpoint["description"] + return openapi_schema + + +app.openapi_schema = custom_openapi() + + +@app.on_event("startup") +@app.get( + "/reload", dependencies=[Depends(authenticated)], tags=["Management"] +) # reload is useful to be able to refresh the table catalog from the database +async def startup_event(): + """Application startup: register the db and create table list.""" + # stac-fastapi, tifeatures, and timvt all have there own nearly identical connect_to_db functions we should sync them up so that we make sure to use a single connection pool across all three + await connect_to_db(app) + await stac_connectdb(app) + + # table catalog between tifeatures and timvt should be synced up and ideally we just use the same catalog for both + await register_table_catalog(app) + return {"Refreshed": True} + + +@app.on_event("shutdown") +async def shutdown_event(): + """Application shutdown: de-register the db.""" + await close_db_connection(app) + await stac_closedb(app) + +@app.get( + "/healthcheck", + tags=["Management"], +) +async def healthcheck(): + """Always return 200 when running.""" + return {"Hello": "World"} + diff --git a/services/stac/api/settings.py b/services/stac/api/settings.py new file mode 100644 index 00000000..715b78db --- /dev/null +++ b/services/stac/api/settings.py @@ -0,0 +1,40 @@ +"""Settings for STAC app.""" + +import os +from typing import Optional + +import boto3 +import orjson +import pydantic + +class Settings(PostgresSettings): + """Settings for RICR API.""" + + name: str = "RICR" + cors_origins: str = "*" + debug: bool = True + session_secret_key: str + oauth_client_id: str + oauth_client_secret: str + oauth_authorize_url: str + oauth_token_url: str + oauth_redirect_uri: str + oauth_user_url: Optional[str] = None + ricr_base_url: Optional[str] = None + mc_test_noauth: bool = False + + @pydantic.validator("cors_origins") + def parse_cors_origin(cls, v): + """Parse CORS origins.""" + return [origin.strip() for origin in v.split(",")] + + class Config: + """Model config.""" + + env_file = ".env" + + +if "SecretARN" in os.environ: + set_env_from_secrets() + +settings = Settings() From 3b7328ad0df166aac90d7e3cebf43e0069472d4a Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 11:02:43 -0700 Subject: [PATCH 08/24] Database migrations are performed by migration task --- services/stac/Dockerfile | 2 -- services/stac/start.sh | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/services/stac/Dockerfile b/services/stac/Dockerfile index 49d443f3..e0a56a97 100644 --- a/services/stac/Dockerfile +++ b/services/stac/Dockerfile @@ -7,8 +7,6 @@ WORKDIR $HOME COPY ./ $HOME/stac WORKDIR $HOME/stac -COPY ./api . - RUN apk add --no-cache bash nodejs npm python3 py3-pip RUN pip install -U pip diff --git a/services/stac/start.sh b/services/stac/start.sh index 59d196b4..51eeaf07 100755 --- a/services/stac/start.sh +++ b/services/stac/start.sh @@ -1,8 +1,3 @@ #!/bin/bash -echo 'Run migrations if not already run' -pypgstac migrate --dsn $DATABASE_URL - -psql $DATABASE_URL -f $(pwd)/mc_ricr_api/dbfuncs.sql - -uvicorn mc_ricr_api.app:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' +uvicorn api.app:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' From 6a264357f0c483286e555d79bb5531c2b560a887 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 11:06:14 -0700 Subject: [PATCH 09/24] Remove relative path code --- services/stac/api/app.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/services/stac/api/app.py b/services/stac/api/app.py index da1c0d21..aa6ee587 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -26,8 +26,6 @@ from stac_fastapi.pgstac.extensions import QueryExtension from stac_fastapi.pgstac.transactions import TransactionsClient from stac_fastapi.pgstac.types.search import PgstacSearch -from starlette.middleware.base import BaseHTTPMiddleware -from starlette_cramjam.middleware import CompressionMiddleware from app.settings import Settings as AppSettings @@ -59,16 +57,6 @@ class Settings(STACSettings, AppSettings): logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) -class StacRouteFixMiddleware(BaseHTTPMiddleware): - async def dispatch(self, request, call_next): - base_url = settings.ricr_base_url or request.base_url._url - url = urlparse(base_url) - request.scope["scheme"] = url.scheme - if request.url.path.startswith("/stac/"): - request.scope["root_path"] = "/stac" - response = await call_next(request) - return response - app = FastAPI( title="Pearl Backend STAC", version="0.0.1", @@ -88,8 +76,6 @@ async def dispatch(self, request, call_next): allow_headers=["*"], ) -app.add_middleware(CompressionMiddleware) - stac = StacApi( settings=settings, extensions=extensions, From 0f57e714651d80c6cf212186aa27a32a5829e5e5 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 11:16:29 -0700 Subject: [PATCH 10/24] Remove settings as it isn't relavent to an open api --- services/stac/api/app.py | 7 ++---- services/stac/api/settings.py | 40 ----------------------------------- 2 files changed, 2 insertions(+), 45 deletions(-) delete mode 100644 services/stac/api/settings.py diff --git a/services/stac/api/app.py b/services/stac/api/app.py index aa6ee587..e020ed11 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -27,11 +27,8 @@ from stac_fastapi.pgstac.transactions import TransactionsClient from stac_fastapi.pgstac.types.search import PgstacSearch -from app.settings import Settings as AppSettings - - # Boiler Plate for Stac FastApi PGStac -class Settings(STACSettings, AppSettings): +class Settings(STACSettings): ... @@ -70,7 +67,7 @@ class Settings(STACSettings, AppSettings): app.add_middleware( CORSMiddleware, - allow_origins=settings.cors_origins, + allow_origins=['*'], allow_credentials=True, allow_methods=["GET", "POST", "OPTIONS"], allow_headers=["*"], diff --git a/services/stac/api/settings.py b/services/stac/api/settings.py deleted file mode 100644 index 715b78db..00000000 --- a/services/stac/api/settings.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Settings for STAC app.""" - -import os -from typing import Optional - -import boto3 -import orjson -import pydantic - -class Settings(PostgresSettings): - """Settings for RICR API.""" - - name: str = "RICR" - cors_origins: str = "*" - debug: bool = True - session_secret_key: str - oauth_client_id: str - oauth_client_secret: str - oauth_authorize_url: str - oauth_token_url: str - oauth_redirect_uri: str - oauth_user_url: Optional[str] = None - ricr_base_url: Optional[str] = None - mc_test_noauth: bool = False - - @pydantic.validator("cors_origins") - def parse_cors_origin(cls, v): - """Parse CORS origins.""" - return [origin.strip() for origin in v.split(",")] - - class Config: - """Model config.""" - - env_file = ".env" - - -if "SecretARN" in os.environ: - set_env_from_secrets() - -settings = Settings() From 3455180b6dc18ddabd53cb449483c3e57fe59e98 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 11:26:11 -0700 Subject: [PATCH 11/24] Set STAC Postgres Vars --- docker-compose.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index fe96cc92..0f135100 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,7 +31,11 @@ services: ports: - "2001:2001" environment: - - Postgres=postgres://docker:docker@postgis:5432/gis + - POSTGRES_PASSWORD=docker + - POSTGRES_USER=docker + - POSTGRES_DB=gis + - POSTGRES_HOST=postgis + - POSTGRES_PORT=5432 postgis: platform: linux/amd64 From 65bfa87a89132b49d26c0664019bcc0ede452ee7 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 11:51:48 -0700 Subject: [PATCH 12/24] Continue refining docker-compose stac service --- docker-compose.yml | 3 +-- services/stac/Dockerfile | 2 +- services/stac/start.sh | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0f135100..e8e1a5aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,14 +22,13 @@ services: stac: platform: linux/amd64 build: ./services/stac/ - command: sh -c "sleep 5; npm run dev" restart: always links: - postgis depends_on: - migration ports: - - "2001:2001" + - "2002:2002" environment: - POSTGRES_PASSWORD=docker - POSTGRES_USER=docker diff --git a/services/stac/Dockerfile b/services/stac/Dockerfile index e0a56a97..200eb9bc 100644 --- a/services/stac/Dockerfile +++ b/services/stac/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.17 -EXPOSE 2001 +EXPOSE 2002 ENV HOME=/home/lulc WORKDIR $HOME diff --git a/services/stac/start.sh b/services/stac/start.sh index 51eeaf07..35106456 100755 --- a/services/stac/start.sh +++ b/services/stac/start.sh @@ -1,3 +1,3 @@ #!/bin/bash -uvicorn api.app:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' +uvicorn api.app:app --host 0.0.0.0 --port 2002 --proxy-headers --forwarded-allow-ips='*' From 8d377a0634141cfd9a81bda6aec24e73e1fff306 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 14:23:32 -0700 Subject: [PATCH 13/24] Get POSTGIS connection working --- docker-compose.yml | 6 ++++-- services/stac/Dockerfile | 5 +++++ services/stac/api/app.py | 45 +--------------------------------------- 3 files changed, 10 insertions(+), 46 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e8e1a5aa..d8dd56f9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,11 +30,13 @@ services: ports: - "2002:2002" environment: - - POSTGRES_PASSWORD=docker + - POSTGRES_PASS=docker - POSTGRES_USER=docker - - POSTGRES_DB=gis + - POSTGRES_DBNAME=gis - POSTGRES_HOST=postgis - POSTGRES_PORT=5432 + - POSTGRES_HOST_READER=postgis + - POSTGRES_HOST_WRITER=postgis postgis: platform: linux/amd64 diff --git a/services/stac/Dockerfile b/services/stac/Dockerfile index 200eb9bc..d572d813 100644 --- a/services/stac/Dockerfile +++ b/services/stac/Dockerfile @@ -1,5 +1,10 @@ FROM alpine:3.17 +ENV POSTGRES_PASS=docker +ENV POSTGRES_USER=docker +ENV POSTGRES_DB=gis +ENV POSTGRES_HOST=postgis + EXPOSE 2002 ENV HOME=/home/lulc diff --git a/services/stac/api/app.py b/services/stac/api/app.py index e020ed11..3451aecd 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -27,12 +27,7 @@ from stac_fastapi.pgstac.transactions import TransactionsClient from stac_fastapi.pgstac.types.search import PgstacSearch -# Boiler Plate for Stac FastApi PGStac -class Settings(STACSettings): - ... - - -settings = Settings() +settings = STACSettings() extensions = [ TransactionExtension( @@ -93,55 +88,17 @@ class Settings(STACSettings): """ -def custom_openapi(): - """ - Read JSON files from folder with over-rides for summaries and descriptions for specific paths and - over-write the same in the OpenAPI schema. - """ - if app.openapi_schema: - return app.openapi_schema - openapi_schema = app.openapi() - for f in TAGS_JSON_FILES: - with f.open() as tags: - endpoints = json.load(tags) - for endpoint in endpoints: - if ( - endpoint["path"] not in openapi_schema["paths"] - or endpoint["method"] not in openapi_schema["paths"][endpoint["path"]] - ): - logger.warn(f"Endpoint not configured correctly for {endpoint['path']}") - continue - openapi_schema["paths"][endpoint["path"]][endpoint["method"]][ - "summary" - ] = endpoint["summary"] - openapi_schema["paths"][endpoint["path"]][endpoint["method"]][ - "description" - ] = endpoint["description"] - return openapi_schema - - -app.openapi_schema = custom_openapi() - - @app.on_event("startup") @app.get( "/reload", dependencies=[Depends(authenticated)], tags=["Management"] ) # reload is useful to be able to refresh the table catalog from the database async def startup_event(): """Application startup: register the db and create table list.""" - # stac-fastapi, tifeatures, and timvt all have there own nearly identical connect_to_db functions we should sync them up so that we make sure to use a single connection pool across all three - await connect_to_db(app) await stac_connectdb(app) - # table catalog between tifeatures and timvt should be synced up and ideally we just use the same catalog for both - await register_table_catalog(app) - return {"Refreshed": True} - - @app.on_event("shutdown") async def shutdown_event(): """Application shutdown: de-register the db.""" - await close_db_connection(app) await stac_closedb(app) @app.get( From ecb41ae7583624eb0a0368a66b93aa4a268db371 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 14:32:47 -0700 Subject: [PATCH 14/24] Continue fixing issues in STAC startup --- services/stac/api/app.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/services/stac/api/app.py b/services/stac/api/app.py index 3451aecd..24f4dd0c 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -19,6 +19,7 @@ TokenPaginationExtension, TransactionExtension, ) +from fastapi.responses import ORJSONResponse from stac_fastapi.pgstac.config import Settings as STACSettings from stac_fastapi.pgstac.core import CoreCrudClient from stac_fastapi.pgstac.db import close_db_connection as stac_closedb @@ -52,14 +53,12 @@ app = FastAPI( title="Pearl Backend STAC", version="0.0.1", - debug=settings.debug, + debug=True ) app.state.settings = settings app.state.router_prefix = "" -app.add_middleware(StacRouteFixMiddleware) - app.add_middleware( CORSMiddleware, allow_origins=['*'], @@ -83,11 +82,6 @@ tags=["STAC"], ) -""" - Setup API doc over-rides for individual endpoints -""" - - @app.on_event("startup") @app.get( "/reload", dependencies=[Depends(authenticated)], tags=["Management"] From d104d6612331389230f85875c8d03dcac062d8e3 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 14:36:41 -0700 Subject: [PATCH 15/24] Remove authenticated checks --- services/stac/api/app.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/services/stac/api/app.py b/services/stac/api/app.py index 24f4dd0c..c3111e07 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -77,15 +77,11 @@ ) app.include_router( stac.router, - dependencies=[Depends(authenticated)], prefix="/stac", tags=["STAC"], ) @app.on_event("startup") -@app.get( - "/reload", dependencies=[Depends(authenticated)], tags=["Management"] -) # reload is useful to be able to refresh the table catalog from the database async def startup_event(): """Application startup: register the db and create table list.""" await stac_connectdb(app) From 46e9f582e5bd57fd209e3988f8057b37b6046df8 Mon Sep 17 00:00:00 2001 From: ingalls Date: Mon, 5 Dec 2022 15:09:49 -0700 Subject: [PATCH 16/24] Fix migration command --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d8dd56f9..5622b795 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,7 +82,7 @@ services: migration: platform: linux/amd64 build: ./services/api - command: sh -c "pgstac --dsn $Postgres pgready && npx knex migrate:latest && pgstac --dsn $Postgres migrate" + command: bash -c "echo $${Postgres} && pypgstac --dsn=$${Postgres} pgready && npx knex migrate:latest && pypgstac --dsn=$${Postgres} migrate" links: - postgis ports: From 6ac1df811e1b1683509ac35de783242f24c15c0d Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 12:33:23 -0700 Subject: [PATCH 17/24] Remove Transaction Extension --- services/stac/api/app.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/services/stac/api/app.py b/services/stac/api/app.py index c3111e07..4de5f3df 100644 --- a/services/stac/api/app.py +++ b/services/stac/api/app.py @@ -17,7 +17,6 @@ FilterExtension, SortExtension, TokenPaginationExtension, - TransactionExtension, ) from fastapi.responses import ORJSONResponse from stac_fastapi.pgstac.config import Settings as STACSettings @@ -25,17 +24,11 @@ from stac_fastapi.pgstac.db import close_db_connection as stac_closedb from stac_fastapi.pgstac.db import connect_to_db as stac_connectdb from stac_fastapi.pgstac.extensions import QueryExtension -from stac_fastapi.pgstac.transactions import TransactionsClient from stac_fastapi.pgstac.types.search import PgstacSearch settings = STACSettings() extensions = [ - TransactionExtension( - client=TransactionsClient(), - settings=settings, - response_class=ORJSONResponse, - ), QueryExtension(), SortExtension(), FieldsExtension(), From f8d6786390054a9ecf129669fc71571e14895583 Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 12:48:36 -0700 Subject: [PATCH 18/24] Add STAC Item Endpoint --- services/api/routes/aoi.js | 22 ++++++++++++++++++++ services/api/schema/req.body.CreateStac.json | 8 +++++++ 2 files changed, 30 insertions(+) create mode 100644 services/api/schema/req.body.CreateStac.json diff --git a/services/api/routes/aoi.js b/services/api/routes/aoi.js index 236dd1b4..3b69ab0d 100644 --- a/services/api/routes/aoi.js +++ b/services/api/routes/aoi.js @@ -480,6 +480,28 @@ export default async function router(schema, config) { } }); + await schema.patch('/project/:projectid/aoi/:aoiid/stac', { + name: 'Create STAC', + group: 'AOI', + auth: 'user', + description: 'Post the AOI to the public STAC Catalogue', + ':projectid': 'integer', + ':aoiid': 'integer', + body: 'req.body.CreateStac.json', + res: 'res.Standard.json' + }, config.requiresAuth, async (req, res) => { + try { + const a = await AOI.has_auth(config.pool, req.auth, req.params.projectid, req.params.aoiid); + + return res.json({ + status: 200, + message: 'Create STAC Item' + }); + } catch (err) { + return Err.respond(err, res); + } + }); + await schema.get('/share/:shareuuid', { name: 'Get Share', group: 'Share', diff --git a/services/api/schema/req.body.CreateStac.json b/services/api/schema/req.body.CreateStac.json new file mode 100644 index 00000000..024a0654 --- /dev/null +++ b/services/api/schema/req.body.CreateStac.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "required": [], + "additionalProperties": false, + "properties": { + + } +} From 3b5f217c23c1e181a55f07436e190751d439f18b Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 12:58:09 -0700 Subject: [PATCH 19/24] Add Trimed down AOI STAC test --- services/api/test/aoi-stac.test.js | 101 +++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 services/api/test/aoi-stac.test.js diff --git a/services/api/test/aoi-stac.test.js b/services/api/test/aoi-stac.test.js new file mode 100644 index 00000000..8d80a28a --- /dev/null +++ b/services/api/test/aoi-stac.test.js @@ -0,0 +1,101 @@ +import test from 'tape'; +import Flight from './flight.js'; +import fs from 'fs'; +import { sql } from 'slonik'; + +const flight = new Flight(); + +flight.init(test); +flight.takeoff(test); +flight.user(test, 'ingalls', true); + +flight.fixture(test, 'model.json', 'ingalls'); +flight.fixture(test, 'project.json', 'ingalls'); +flight.fixture(test, 'checkpoint.json', 'ingalls'); + +test('POST /api/project/1/aoi', async (t) => { + try { + const res = await flight.request({ + json: true, + url: '/api/project/1/aoi', + method: 'POST', + headers: { + Authorization: `Bearer ${flight.token.ingalls}` + }, + body: { + name: 'Test AOI', + checkpoint_id: 1, + bounds: { + type: 'Polygon', + coordinates: [[ + [-79.37724530696869, 38.83428180092151], + [-79.37677592039108, 38.83428180092151], + [-79.37677592039108, 38.83455550411051], + [-79.37724530696869, 38.83455550411051], + [-79.37724530696869, 38.83428180092151] + ]] + } + } + }, t); + + t.ok(res.body.created, '.created: '); + delete res.body.created; + + t.deepEquals(res.body, { + id: 1, + area: 1238, + storage: false, + project_id: 1, + checkpoint_id: 1, + bookmarked: false, + bookmarked_at: null, + patches: [], + name: 'Test AOI', + px_stats: {}, + classes: [ + { name: 'Water', color: '#0000FF' }, + { name: 'Tree Canopy', color: '#008000' }, + { name: 'Field', color: '#80FF80' }, + { name: 'Built', color: '#806060' } + ], + bounds: { + type: 'Polygon', + bounds: [ + -79.37724530696869, + 38.83428180092151, + -79.37677592039108, + 38.83455550411051 + ], + coordinates: [[ + [-79.37724530696869, 38.83428180092151], + [-79.37677592039108, 38.83428180092151], + [-79.37677592039108, 38.83455550411051], + [-79.37724530696869, 38.83455550411051], + [-79.37724530696869, 38.83428180092151] + ]] + } + }); + + } catch (err) { + t.error(err, 'no errors'); + } + + t.end(); +}); + +test('[meta] Set aoi.storage: true', async (t) => { + try { + await flight.config.pool.query(sql` + UPDATE + aois + SET + storage = true + `, []); + } catch (err) { + t.error(err, 'no errors'); + } + + t.end(); +}); + +flight.landing(test); From 637f7708bf95242de59227aa3292bc04ed1ef3b8 Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 13:18:53 -0700 Subject: [PATCH 20/24] Set up /stac tests --- services/api/doc/api.js | 19 + services/api/package-lock.json | 426 ++++++++++----------- services/api/routes/aoi.js | 3 +- services/api/test/aoi-stac.test.js | 43 +++ services/api/test/fixtures/get_schema.json | 5 + 5 files changed, 282 insertions(+), 214 deletions(-) diff --git a/services/api/doc/api.js b/services/api/doc/api.js index 146afa58..e1125ff4 100644 --- a/services/api/doc/api.js +++ b/services/api/doc/api.js @@ -447,6 +447,25 @@ Note: this is an internal API that is called by the websocket GPU */ +/** +* @api {post} /project/:projectid/aoi/:aoiid/stac Create STAC +* @apiVersion 1.0.0 +* @apiName POST-/project/:projectid/aoi/:aoiid/stac +* @apiGroup AOI +* @apiPermission user +* +* @apidescription +* Post the AOI to the public STAC Catalogue +* +* @apiParam {integer} projectid param +* @apiParam {integer} aoiid param +* +* +* @apiSchema (Body) {jsonschema=../schema/req.body.CreateStac.json} apiParam +* @apiSchema {jsonschema=../schema/res.Standard.json} apiSuccess +*/ + + /** * @api {get} /share/:shareuuid Get Share * @apiVersion 1.0.0 diff --git a/services/api/package-lock.json b/services/api/package-lock.json index 26491e3e..9a013a3d 100644 --- a/services/api/package-lock.json +++ b/services/api/package-lock.json @@ -214,9 +214,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.16.tgz", - "integrity": "sha512-nyB6CH++2mSgx3GbnrJsZSxzne5K0HMyNIWafDHqYy7IwxFc4fd/CgHVZXr8Eh+Q3KbIAcAe3vGyqIPhGblvMQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", "cpu": [ "arm" ], @@ -229,9 +229,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.16.tgz", - "integrity": "sha512-SDLfP1uoB0HZ14CdVYgagllgrG7Mdxhkt4jDJOKl/MldKrkQ6vDJMZKl2+5XsEY/Lzz37fjgLQoJBGuAw/x8kQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", "cpu": [ "loong64" ], @@ -1653,9 +1653,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==", + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==", "funding": [ { "type": "opencollective", @@ -2333,9 +2333,9 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" }, "node_modules/esbuild": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.16.tgz", - "integrity": "sha512-o6iS9zxdHrrojjlj6pNGC2NAg86ECZqIETswTM5KmJitq+R1YmahhWtMumeQp9lHqJaROGnsBi2RLawGnfo5ZQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -2344,34 +2344,34 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.16", - "@esbuild/linux-loong64": "0.15.16", - "esbuild-android-64": "0.15.16", - "esbuild-android-arm64": "0.15.16", - "esbuild-darwin-64": "0.15.16", - "esbuild-darwin-arm64": "0.15.16", - "esbuild-freebsd-64": "0.15.16", - "esbuild-freebsd-arm64": "0.15.16", - "esbuild-linux-32": "0.15.16", - "esbuild-linux-64": "0.15.16", - "esbuild-linux-arm": "0.15.16", - "esbuild-linux-arm64": "0.15.16", - "esbuild-linux-mips64le": "0.15.16", - "esbuild-linux-ppc64le": "0.15.16", - "esbuild-linux-riscv64": "0.15.16", - "esbuild-linux-s390x": "0.15.16", - "esbuild-netbsd-64": "0.15.16", - "esbuild-openbsd-64": "0.15.16", - "esbuild-sunos-64": "0.15.16", - "esbuild-windows-32": "0.15.16", - "esbuild-windows-64": "0.15.16", - "esbuild-windows-arm64": "0.15.16" + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" } }, "node_modules/esbuild-android-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.16.tgz", - "integrity": "sha512-Vwkv/sT0zMSgPSVO3Jlt1pUbnZuOgtOQJkJkyyJFAlLe7BiT8e9ESzo0zQSx4c3wW4T6kGChmKDPMbWTgtliQA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", "cpu": [ "x64" ], @@ -2384,9 +2384,9 @@ } }, "node_modules/esbuild-android-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.16.tgz", - "integrity": "sha512-lqfKuofMExL5niNV3gnhMUYacSXfsvzTa/58sDlBET/hCOG99Zmeh+lz6kvdgvGOsImeo6J9SW21rFCogNPLxg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", "cpu": [ "arm64" ], @@ -2399,9 +2399,9 @@ } }, "node_modules/esbuild-darwin-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.16.tgz", - "integrity": "sha512-wo2VWk/n/9V2TmqUZ/KpzRjCEcr00n7yahEdmtzlrfQ3lfMCf3Wa+0sqHAbjk3C6CKkR3WKK/whkMq5Gj4Da9g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", "cpu": [ "x64" ], @@ -2414,9 +2414,9 @@ } }, "node_modules/esbuild-darwin-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.16.tgz", - "integrity": "sha512-fMXaUr5ou0M4WnewBKsspMtX++C1yIa3nJ5R2LSbLCfJT3uFdcRoU/NZjoM4kOMKyOD9Sa/2vlgN8G07K3SJnw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", "cpu": [ "arm64" ], @@ -2429,9 +2429,9 @@ } }, "node_modules/esbuild-freebsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.16.tgz", - "integrity": "sha512-UzIc0xlRx5x9kRuMr+E3+hlSOxa/aRqfuMfiYBXu2jJ8Mzej4lGL7+o6F5hzhLqWfWm1GWHNakIdlqg1ayaTNQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", "cpu": [ "x64" ], @@ -2444,9 +2444,9 @@ } }, "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.16.tgz", - "integrity": "sha512-8xyiYuGc0DLZphFQIiYaLHlfoP+hAN9RHbE+Ibh8EUcDNHAqbQgUrQg7pE7Bo00rXmQ5Ap6KFgcR0b4ALZls1g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", "cpu": [ "arm64" ], @@ -2459,9 +2459,9 @@ } }, "node_modules/esbuild-linux-32": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.16.tgz", - "integrity": "sha512-iGijUTV+0kIMyUVoynK0v+32Oi8yyp0xwMzX69GX+5+AniNy/C/AL1MjFTsozRp/3xQPl7jVux/PLe2ds10/2w==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", "cpu": [ "ia32" ], @@ -2474,9 +2474,9 @@ } }, "node_modules/esbuild-linux-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.16.tgz", - "integrity": "sha512-tuSOjXdLw7VzaUj89fIdAaQT7zFGbKBcz4YxbWrOiXkwscYgE7HtTxUavreBbnRkGxKwr9iT/gmeJWNm4djy/g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", "cpu": [ "x64" ], @@ -2489,9 +2489,9 @@ } }, "node_modules/esbuild-linux-arm": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.16.tgz", - "integrity": "sha512-XKcrxCEXDTOuoRj5l12tJnkvuxXBMKwEC5j0JISw3ziLf0j4zIwXbKbTmUrKFWbo6ZgvNpa7Y5dnbsjVvH39bQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", "cpu": [ "arm" ], @@ -2504,9 +2504,9 @@ } }, "node_modules/esbuild-linux-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.16.tgz", - "integrity": "sha512-mPYksnfHnemNrvjrDhZyixL/AfbJN0Xn9S34ZOHYdh6/jJcNd8iTsv3JwJoEvTJqjMggjMhGUPJAdjnFBHoH8A==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", "cpu": [ "arm64" ], @@ -2519,9 +2519,9 @@ } }, "node_modules/esbuild-linux-mips64le": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.16.tgz", - "integrity": "sha512-kSJO2PXaxfm0pWY39+YX+QtpFqyyrcp0ZeI8QPTrcFVQoWEPiPVtOfTZeS3ZKedfH+Ga38c4DSzmKMQJocQv6A==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", "cpu": [ "mips64el" ], @@ -2534,9 +2534,9 @@ } }, "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.16.tgz", - "integrity": "sha512-NimPikwkBY0yGABw6SlhKrtT35sU4O23xkhlrTT/O6lSxv3Pm5iSc6OYaqVAHWkLdVf31bF4UDVFO+D990WpAA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", "cpu": [ "ppc64" ], @@ -2549,9 +2549,9 @@ } }, "node_modules/esbuild-linux-riscv64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.16.tgz", - "integrity": "sha512-ty2YUHZlwFOwp7pR+J87M4CVrXJIf5ZZtU/umpxgVJBXvWjhziSLEQxvl30SYfUPq0nzeWKBGw5i/DieiHeKfw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", "cpu": [ "riscv64" ], @@ -2564,9 +2564,9 @@ } }, "node_modules/esbuild-linux-s390x": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.16.tgz", - "integrity": "sha512-VkZaGssvPDQtx4fvVdZ9czezmyWyzpQhEbSNsHZZN0BHvxRLOYAQ7sjay8nMQwYswP6O2KlZluRMNPYefFRs+w==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", "cpu": [ "s390x" ], @@ -2598,9 +2598,9 @@ } }, "node_modules/esbuild-netbsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.16.tgz", - "integrity": "sha512-ElQ9rhdY51et6MJTWrCPbqOd/YuPowD7Cxx3ee8wlmXQQVW7UvQI6nSprJ9uVFQISqSF5e5EWpwWqXZsECLvXg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", "cpu": [ "x64" ], @@ -2613,9 +2613,9 @@ } }, "node_modules/esbuild-openbsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.16.tgz", - "integrity": "sha512-KgxMHyxMCT+NdLQE1zVJEsLSt2QQBAvJfmUGDmgEq8Fvjrf6vSKB00dVHUEDKcJwMID6CdgCpvYNt999tIYhqA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", "cpu": [ "x64" ], @@ -2628,9 +2628,9 @@ } }, "node_modules/esbuild-sunos-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.16.tgz", - "integrity": "sha512-exSAx8Phj7QylXHlMfIyEfNrmqnLxFqLxdQF6MBHPdHAjT7fsKaX6XIJn+aQEFiOcE4X8e7VvdMCJ+WDZxjSRQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", "cpu": [ "x64" ], @@ -2643,9 +2643,9 @@ } }, "node_modules/esbuild-windows-32": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.16.tgz", - "integrity": "sha512-zQgWpY5pUCSTOwqKQ6/vOCJfRssTvxFuEkpB4f2VUGPBpdddZfdj8hbZuFRdZRPIVHvN7juGcpgCA/XCF37mAQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", "cpu": [ "ia32" ], @@ -2658,9 +2658,9 @@ } }, "node_modules/esbuild-windows-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.16.tgz", - "integrity": "sha512-HjW1hHRLSncnM3MBCP7iquatHVJq9l0S2xxsHHj4yzf4nm9TU4Z7k4NkeMlD/dHQ4jPlQQhwcMvwbJiOefSuZw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", "cpu": [ "x64" ], @@ -2673,9 +2673,9 @@ } }, "node_modules/esbuild-windows-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.16.tgz", - "integrity": "sha512-oCcUKrJaMn04Vxy9Ekd8x23O8LoU01+4NOkQ2iBToKgnGj5eo1vU9i27NQZ9qC8NFZgnQQZg5oZWAejmbsppNA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", "cpu": [ "arm64" ], @@ -2713,9 +2713,9 @@ } }, "node_modules/eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.3.3", @@ -3287,9 +3287,9 @@ } }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3673,9 +3673,9 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7424,9 +7424,9 @@ } }, "node_modules/terser": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.0.tgz", - "integrity": "sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -8354,15 +8354,15 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@esbuild/android-arm": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.16.tgz", - "integrity": "sha512-nyB6CH++2mSgx3GbnrJsZSxzne5K0HMyNIWafDHqYy7IwxFc4fd/CgHVZXr8Eh+Q3KbIAcAe3vGyqIPhGblvMQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.16.tgz", - "integrity": "sha512-SDLfP1uoB0HZ14CdVYgagllgrG7Mdxhkt4jDJOKl/MldKrkQ6vDJMZKl2+5XsEY/Lzz37fjgLQoJBGuAw/x8kQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", "optional": true }, "@eslint/eslintrc": { @@ -9500,9 +9500,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==" + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==" }, "caseless": { "version": "0.12.0", @@ -10018,116 +10018,116 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" }, "esbuild": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.16.tgz", - "integrity": "sha512-o6iS9zxdHrrojjlj6pNGC2NAg86ECZqIETswTM5KmJitq+R1YmahhWtMumeQp9lHqJaROGnsBi2RLawGnfo5ZQ==", - "requires": { - "@esbuild/android-arm": "0.15.16", - "@esbuild/linux-loong64": "0.15.16", - "esbuild-android-64": "0.15.16", - "esbuild-android-arm64": "0.15.16", - "esbuild-darwin-64": "0.15.16", - "esbuild-darwin-arm64": "0.15.16", - "esbuild-freebsd-64": "0.15.16", - "esbuild-freebsd-arm64": "0.15.16", - "esbuild-linux-32": "0.15.16", - "esbuild-linux-64": "0.15.16", - "esbuild-linux-arm": "0.15.16", - "esbuild-linux-arm64": "0.15.16", - "esbuild-linux-mips64le": "0.15.16", - "esbuild-linux-ppc64le": "0.15.16", - "esbuild-linux-riscv64": "0.15.16", - "esbuild-linux-s390x": "0.15.16", - "esbuild-netbsd-64": "0.15.16", - "esbuild-openbsd-64": "0.15.16", - "esbuild-sunos-64": "0.15.16", - "esbuild-windows-32": "0.15.16", - "esbuild-windows-64": "0.15.16", - "esbuild-windows-arm64": "0.15.16" + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" } }, "esbuild-android-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.16.tgz", - "integrity": "sha512-Vwkv/sT0zMSgPSVO3Jlt1pUbnZuOgtOQJkJkyyJFAlLe7BiT8e9ESzo0zQSx4c3wW4T6kGChmKDPMbWTgtliQA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", "optional": true }, "esbuild-android-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.16.tgz", - "integrity": "sha512-lqfKuofMExL5niNV3gnhMUYacSXfsvzTa/58sDlBET/hCOG99Zmeh+lz6kvdgvGOsImeo6J9SW21rFCogNPLxg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", "optional": true }, "esbuild-darwin-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.16.tgz", - "integrity": "sha512-wo2VWk/n/9V2TmqUZ/KpzRjCEcr00n7yahEdmtzlrfQ3lfMCf3Wa+0sqHAbjk3C6CKkR3WKK/whkMq5Gj4Da9g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", "optional": true }, "esbuild-darwin-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.16.tgz", - "integrity": "sha512-fMXaUr5ou0M4WnewBKsspMtX++C1yIa3nJ5R2LSbLCfJT3uFdcRoU/NZjoM4kOMKyOD9Sa/2vlgN8G07K3SJnw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", "optional": true }, "esbuild-freebsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.16.tgz", - "integrity": "sha512-UzIc0xlRx5x9kRuMr+E3+hlSOxa/aRqfuMfiYBXu2jJ8Mzej4lGL7+o6F5hzhLqWfWm1GWHNakIdlqg1ayaTNQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.16.tgz", - "integrity": "sha512-8xyiYuGc0DLZphFQIiYaLHlfoP+hAN9RHbE+Ibh8EUcDNHAqbQgUrQg7pE7Bo00rXmQ5Ap6KFgcR0b4ALZls1g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", "optional": true }, "esbuild-linux-32": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.16.tgz", - "integrity": "sha512-iGijUTV+0kIMyUVoynK0v+32Oi8yyp0xwMzX69GX+5+AniNy/C/AL1MjFTsozRp/3xQPl7jVux/PLe2ds10/2w==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", "optional": true }, "esbuild-linux-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.16.tgz", - "integrity": "sha512-tuSOjXdLw7VzaUj89fIdAaQT7zFGbKBcz4YxbWrOiXkwscYgE7HtTxUavreBbnRkGxKwr9iT/gmeJWNm4djy/g==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", "optional": true }, "esbuild-linux-arm": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.16.tgz", - "integrity": "sha512-XKcrxCEXDTOuoRj5l12tJnkvuxXBMKwEC5j0JISw3ziLf0j4zIwXbKbTmUrKFWbo6ZgvNpa7Y5dnbsjVvH39bQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", "optional": true }, "esbuild-linux-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.16.tgz", - "integrity": "sha512-mPYksnfHnemNrvjrDhZyixL/AfbJN0Xn9S34ZOHYdh6/jJcNd8iTsv3JwJoEvTJqjMggjMhGUPJAdjnFBHoH8A==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", "optional": true }, "esbuild-linux-mips64le": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.16.tgz", - "integrity": "sha512-kSJO2PXaxfm0pWY39+YX+QtpFqyyrcp0ZeI8QPTrcFVQoWEPiPVtOfTZeS3ZKedfH+Ga38c4DSzmKMQJocQv6A==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.16.tgz", - "integrity": "sha512-NimPikwkBY0yGABw6SlhKrtT35sU4O23xkhlrTT/O6lSxv3Pm5iSc6OYaqVAHWkLdVf31bF4UDVFO+D990WpAA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", "optional": true }, "esbuild-linux-riscv64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.16.tgz", - "integrity": "sha512-ty2YUHZlwFOwp7pR+J87M4CVrXJIf5ZZtU/umpxgVJBXvWjhziSLEQxvl30SYfUPq0nzeWKBGw5i/DieiHeKfw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", "optional": true }, "esbuild-linux-s390x": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.16.tgz", - "integrity": "sha512-VkZaGssvPDQtx4fvVdZ9czezmyWyzpQhEbSNsHZZN0BHvxRLOYAQ7sjay8nMQwYswP6O2KlZluRMNPYefFRs+w==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", "optional": true }, "esbuild-loader": { @@ -10144,39 +10144,39 @@ } }, "esbuild-netbsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.16.tgz", - "integrity": "sha512-ElQ9rhdY51et6MJTWrCPbqOd/YuPowD7Cxx3ee8wlmXQQVW7UvQI6nSprJ9uVFQISqSF5e5EWpwWqXZsECLvXg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", "optional": true }, "esbuild-openbsd-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.16.tgz", - "integrity": "sha512-KgxMHyxMCT+NdLQE1zVJEsLSt2QQBAvJfmUGDmgEq8Fvjrf6vSKB00dVHUEDKcJwMID6CdgCpvYNt999tIYhqA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", "optional": true }, "esbuild-sunos-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.16.tgz", - "integrity": "sha512-exSAx8Phj7QylXHlMfIyEfNrmqnLxFqLxdQF6MBHPdHAjT7fsKaX6XIJn+aQEFiOcE4X8e7VvdMCJ+WDZxjSRQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", "optional": true }, "esbuild-windows-32": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.16.tgz", - "integrity": "sha512-zQgWpY5pUCSTOwqKQ6/vOCJfRssTvxFuEkpB4f2VUGPBpdddZfdj8hbZuFRdZRPIVHvN7juGcpgCA/XCF37mAQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", "optional": true }, "esbuild-windows-64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.16.tgz", - "integrity": "sha512-HjW1hHRLSncnM3MBCP7iquatHVJq9l0S2xxsHHj4yzf4nm9TU4Z7k4NkeMlD/dHQ4jPlQQhwcMvwbJiOefSuZw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", "optional": true }, "esbuild-windows-arm64": { - "version": "0.15.16", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.16.tgz", - "integrity": "sha512-oCcUKrJaMn04Vxy9Ekd8x23O8LoU01+4NOkQ2iBToKgnGj5eo1vU9i27NQZ9qC8NFZgnQQZg5oZWAejmbsppNA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", "optional": true }, "escalade": { @@ -10196,9 +10196,9 @@ "dev": true }, "eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dev": true, "requires": { "@eslint/eslintrc": "^1.3.3", @@ -10633,9 +10633,9 @@ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==" }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -10921,9 +10921,9 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "requires": { "brace-expansion": "^2.0.1" } @@ -13711,9 +13711,9 @@ "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==" }, "terser": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.0.tgz", - "integrity": "sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", diff --git a/services/api/routes/aoi.js b/services/api/routes/aoi.js index 3b69ab0d..c6e91056 100644 --- a/services/api/routes/aoi.js +++ b/services/api/routes/aoi.js @@ -480,7 +480,7 @@ export default async function router(schema, config) { } }); - await schema.patch('/project/:projectid/aoi/:aoiid/stac', { + await schema.post('/project/:projectid/aoi/:aoiid/stac', { name: 'Create STAC', group: 'AOI', auth: 'user', @@ -492,6 +492,7 @@ export default async function router(schema, config) { }, config.requiresAuth, async (req, res) => { try { const a = await AOI.has_auth(config.pool, req.auth, req.params.projectid, req.params.aoiid); + if (!a.storage) throw new Err(404, null, 'AOI has not been uploaded'); return res.json({ status: 200, diff --git a/services/api/test/aoi-stac.test.js b/services/api/test/aoi-stac.test.js index 8d80a28a..13653f83 100644 --- a/services/api/test/aoi-stac.test.js +++ b/services/api/test/aoi-stac.test.js @@ -83,6 +83,30 @@ test('POST /api/project/1/aoi', async (t) => { t.end(); }); +test('POST /api/project/1/aoi/1/stac - no storage', async (t) => { + try { + const res = await flight.request({ + json: true, + url: '/api/project/1/aoi/1/stac', + method: 'POST', + headers: { + Authorization: `Bearer ${flight.token.ingalls}` + }, + body: {} + }, false); + + t.deepEquals(res.body, { + status: 404, + message: 'AOI has not been uploaded', + messages: [] + }); + } catch (err) { + t.error(err, 'no errors'); + } + + t.end(); +}); + test('[meta] Set aoi.storage: true', async (t) => { try { await flight.config.pool.query(sql` @@ -98,4 +122,23 @@ test('[meta] Set aoi.storage: true', async (t) => { t.end(); }); +test('POST /api/project/1/aoi/1/stac', async (t) => { + try { + const res = await flight.request({ + json: true, + url: '/api/project/1/aoi/1/stac', + method: 'POST', + headers: { + Authorization: `Bearer ${flight.token.ingalls}` + }, + body: { + } + }, t); + } catch (err) { + t.error(err, 'no errors'); + } + + t.end(); +}); + flight.landing(test); diff --git a/services/api/test/fixtures/get_schema.json b/services/api/test/fixtures/get_schema.json index 9d81d166..c8062f8e 100644 --- a/services/api/test/fixtures/get_schema.json +++ b/services/api/test/fixtures/get_schema.json @@ -109,6 +109,11 @@ "query": false, "res": true }, + "POST /project/:projectid/aoi/:aoiid/stac": { + "body": true, + "query": false, + "res": true + }, "GET /share/:shareuuid": { "body": false, "query": false, From 241abb7fbac599fad14bad1c92c5f8e8dba9012d Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 13:37:02 -0700 Subject: [PATCH 21/24] Call STAC item insertion --- services/api/routes/aoi.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/api/routes/aoi.js b/services/api/routes/aoi.js index c6e91056..844de805 100644 --- a/services/api/routes/aoi.js +++ b/services/api/routes/aoi.js @@ -494,6 +494,12 @@ export default async function router(schema, config) { const a = await AOI.has_auth(config.pool, req.auth, req.params.projectid, req.params.aoiid); if (!a.storage) throw new Err(404, null, 'AOI has not been uploaded'); + await config.pool.query(sql` + SELECT pgstac.create_item(${JSON.stringify({ + + })}::JSONB); + `); + return res.json({ status: 200, message: 'Create STAC Item' From 62171d870fd250dcce8211b96411fdd2ea9f2b27 Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 14:06:57 -0700 Subject: [PATCH 22/24] Upsert Collection & item --- services/api/routes/aoi.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/services/api/routes/aoi.js b/services/api/routes/aoi.js index 844de805..e554e54f 100644 --- a/services/api/routes/aoi.js +++ b/services/api/routes/aoi.js @@ -495,8 +495,28 @@ export default async function router(schema, config) { if (!a.storage) throw new Err(404, null, 'AOI has not been uploaded'); await config.pool.query(sql` - SELECT pgstac.create_item(${JSON.stringify({ + SELECT pgstac.upsert_collection(${JSON.stringify({ + stac_version: "1.0.0", + type: "Catalog", + id: a.project_id, + description: `Project ID: ${a.project_id}`, + links: [] + })}::JSONB); + `) + await config.pool.query(sql` + SELECT pgstac.upsert_item(${JSON.stringify({ + stac_version: "1.0.0", + collection: a.project_id, + type: "Feature", + id: a.id, + bbox: a.bounds.bounds, + geometry: a.bounds, + properties: { + datetime: (new Date(a.created)).toISOString(), + }, + links: [], + assets: {} })}::JSONB); `); From 682d6915e9c1b75897bcaeb4fcda898bfa645710 Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 14:12:49 -0700 Subject: [PATCH 23/24] Publish STAC Item --- services/api/test/aoi-stac.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/api/test/aoi-stac.test.js b/services/api/test/aoi-stac.test.js index 13653f83..edcd737c 100644 --- a/services/api/test/aoi-stac.test.js +++ b/services/api/test/aoi-stac.test.js @@ -141,4 +141,23 @@ test('POST /api/project/1/aoi/1/stac', async (t) => { t.end(); }); +test('POST /api/project/1/aoi/1/stac - duplicate should pass', async (t) => { + try { + const res = await flight.request({ + json: true, + url: '/api/project/1/aoi/1/stac', + method: 'POST', + headers: { + Authorization: `Bearer ${flight.token.ingalls}` + }, + body: { + } + }, t); + } catch (err) { + t.error(err, 'no errors'); + } + + t.end(); +}); + flight.landing(test); From 9775747e388af68e96928add36c581a7a14294c6 Mon Sep 17 00:00:00 2001 From: ingalls Date: Tue, 6 Dec 2022 14:17:32 -0700 Subject: [PATCH 24/24] add basic asset --- services/api/routes/aoi.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/services/api/routes/aoi.js b/services/api/routes/aoi.js index e554e54f..4a86c3aa 100644 --- a/services/api/routes/aoi.js +++ b/services/api/routes/aoi.js @@ -516,7 +516,14 @@ export default async function router(schema, config) { datetime: (new Date(a.created)).toISOString(), }, links: [], - assets: {} + assets: { + visual: { + href: 'URL HERE', + type: 'image/tiff; application=geotiff; profile=cloud-optimized', + title: `Project: ${a.project_id} - AOI: ${a.id}`, + roles: [ 'visual' ] + } + } })}::JSONB); `);