diff --git a/.circleci/config.yml b/.circleci/config.yml index 130ad52..6f26168 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,33 +1,54 @@ version: 2.1 orbs: - aws-cli: circleci/aws-cli@4.0 - aws-ecr: circleci/aws-ecr@9.0 - + aws-cli: circleci/aws-cli@5.1.0 + aws-ecr: circleci/aws-ecr@9.3.2 jobs: - build_and_push: - docker: - - image: cimg/base:current - steps: - - checkout - - setup_remote_docker - - run: - name: Build Details. - command: | - echo "Building Docker image using aws-ecr Orb commands." - docker --version - - - aws-ecr/ecr_login: - region: us-east-1 - - - aws-ecr/build_image: - region: us-east-1 - repo: gaiagps/elevation-service - dockerfile: Dockerfile - tag: ${CIRCLE_SHA1} + test: + docker: + - image: cimg/node:lts + steps: + - checkout + - aws-cli/setup + - run: + name: Setup pnpm + command: sudo corepack enable && pnpm config set store-dir .pnpm-store + - restore_cache: + name: Restore pnpm store + keys: + - pnpm-{{ checksum "pnpm-lock.yaml" }} + - run: + name: Run tests + command: pnpm test:ci + - save_cache: + name: Save pnpm store + key: pnpm-{{ checksum "pnpm-lock.yaml" }} + paths: + - .pnpm-store + ecr: + docker: + - image: cimg/base:current + steps: + - setup_remote_docker: + docker_layer_caching: true + - aws-ecr/build_and_push_image: + auth: + - aws-cli/setup + repo: gaiagps/elevation-service + tag: ${CIRCLE_SHA1} workflows: - staging: - jobs: - - build_and_push + elevation: + jobs: + - test: + name: Tests + - ecr: + name: ECR + requires: + - Tests +# filters: +# branches: +# only: +# - master +# tags: diff --git a/.test.env b/.test.env new file mode 100644 index 0000000..096c7f2 --- /dev/null +++ b/.test.env @@ -0,0 +1,8 @@ +PORT="5001" +TILE_DIRECTORY="elevation-server-data" +CONNECTION_TIMEOUT="70000" +KEEP_ALIVE_TIMEOUT="65000" +MAX_POST_SIZE="500000" +MAX_LRU_SIZE="500000000" +AWS_REGION="us-east-1" +AWS_ELEVATION_BUCKET="com.gaiagps.dem" diff --git a/package.json b/package.json index f63efb8..8e23037 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elevation-service", - "packageManager": "pnpm@9.1.0", + "packageManager": "pnpm@9.9.0", "type": "module", "private": true, "version": "3.0.0", @@ -8,9 +8,10 @@ "start": "node --require dd-trace/init dist/server.js", "dev": "pnpm build; concurrently \"pnpm:dev:*\"", "dev:watch": "tsc --watch", - "dev:start": "nodemon --watch 'dist' --exec 'pnpm start'", + "dev:start": "nodemon --watch 'dist' --exec 'NODE_ENV=development pnpm start'", "build": "tsc", - "test": "node --test --test-concurrency=1" + "test": "NODE_ENV=test node --test --test-concurrency=1", + "test:ci": "pnpm install && pnpm build && pnpm test" }, "dependencies": { "@aws-sdk/client-s3": "^3.588.0", @@ -27,19 +28,19 @@ "pbf": "^3.2.1" }, "devDependencies": { - "@eslint/js": "^9.4.0", + "@eslint/js": "^9.9.1", "@types/geobuf": "^3.0.4", "@types/geojson": "^7946.0.14", "@types/mapbox__polyline": "^1.0.5", - "@types/node": "^20.14.1", + "@types/node": "^22.5.4", "@types/pbf": "^3.0.5", "concurrently": "^8.2.2", - "eslint": "^9.4.0", + "eslint": "^9.9.1", "geojson": "^0.5.0", - "globals": "^15.3.0", - "nodemon": "^3.1.3", - "prettier": "^3.3.0", - "typescript": "^5.4.5", - "typescript-eslint": "^7.12.0" + "globals": "^15.9.0", + "nodemon": "^3.1.4", + "prettier": "^3.3.3", + "typescript": "^5.5.4", + "typescript-eslint": "^8.4.0" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac89399..9093b5f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,8 +46,8 @@ importers: version: 3.2.1 devDependencies: '@eslint/js': - specifier: ^9.4.0 - version: 9.4.0 + specifier: ^9.9.1 + version: 9.9.1 '@types/geobuf': specifier: ^3.0.4 version: 3.0.4 @@ -58,8 +58,8 @@ importers: specifier: ^1.0.5 version: 1.0.5 '@types/node': - specifier: ^20.14.1 - version: 20.14.2 + specifier: ^22.5.4 + version: 22.5.4 '@types/pbf': specifier: ^3.0.5 version: 3.0.5 @@ -67,33 +67,29 @@ importers: specifier: ^8.2.2 version: 8.2.2 eslint: - specifier: ^9.4.0 - version: 9.4.0 + specifier: ^9.9.1 + version: 9.9.1 geojson: specifier: ^0.5.0 version: 0.5.0 globals: - specifier: ^15.3.0 - version: 15.4.0 + specifier: ^15.9.0 + version: 15.9.0 nodemon: - specifier: ^3.1.3 - version: 3.1.3 + specifier: ^3.1.4 + version: 3.1.4 prettier: - specifier: ^3.3.0 - version: 3.3.1 + specifier: ^3.3.3 + version: 3.3.3 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.4 + version: 5.5.4 typescript-eslint: - specifier: ^7.12.0 - version: 7.12.0(eslint@9.4.0)(typescript@5.4.5) + specifier: ^8.4.0 + version: 8.4.0(eslint@9.9.1)(typescript@5.5.4) packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@aws-crypto/crc32@3.0.0': resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} @@ -307,24 +303,24 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.15.1': - resolution: {integrity: sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==} + '@eslint/config-array@0.18.0': + resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.4.0': - resolution: {integrity: sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==} + '@eslint/js@9.9.1': + resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.3': - resolution: {integrity: sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==} + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@fastify/accept-negotiator@1.1.0': @@ -630,8 +626,8 @@ packages: '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/node@20.14.2': - resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} + '@types/node@22.5.4': + resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -639,66 +635,62 @@ packages: '@types/pbf@3.0.5': resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} - '@typescript-eslint/eslint-plugin@7.12.0': - resolution: {integrity: sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.4.0': + resolution: {integrity: sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@7.12.0': - resolution: {integrity: sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.4.0': + resolution: {integrity: sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@7.12.0': - resolution: {integrity: sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.4.0': + resolution: {integrity: sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@7.12.0': - resolution: {integrity: sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/type-utils@8.4.0': + resolution: {integrity: sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@7.12.0': - resolution: {integrity: sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@8.4.0': + resolution: {integrity: sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@7.12.0': - resolution: {integrity: sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@8.4.0': + resolution: {integrity: sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/utils@7.12.0': - resolution: {integrity: sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/utils@8.4.0': + resolution: {integrity: sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/visitor-keys@7.12.0': - resolution: {integrity: sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==} - engines: {node: ^18.18.0 || >=20.0.0} + eslint: ^8.57.0 || ^9.0.0 - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + '@typescript-eslint/visitor-keys@8.4.0': + resolution: {integrity: sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -717,8 +709,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true @@ -761,10 +753,6 @@ packages: array-source@0.0.4: resolution: {integrity: sha512-frNdc+zBn80vipY+GdcJkLEbMWj3xmzArYApmUGxoiV8uAu/ygcs9icPdsGdA26h0MkHUMW6EN2piIvVx+M5Mw==} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} @@ -795,8 +783,8 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} buffer-from@1.1.2: @@ -890,8 +878,8 @@ packages: resolution: {integrity: sha512-4X8iw1ng7rX+iE3uzZoV0MiMpMO6bEsSQ0oRNFDOG0zYvTBkWjbB11Bn5WAOpkZfwHLIw+rSMW05GgfhyWauYw==} engines: {node: '>=18'} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -918,10 +906,6 @@ packages: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} @@ -953,8 +937,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-scope@8.0.1: - resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -965,17 +949,22 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.4.0: - resolution: {integrity: sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==} + eslint@9.9.1: + resolution: {integrity: sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true - espree@10.0.1: - resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -1053,8 +1042,8 @@ packages: file-source@0.6.1: resolution: {integrity: sha512-1R1KneL7eTXmXfKxC10V/9NeGOdbsAXJ+lQ//fvvcHUgtaZcZDWNJNblxAoVOyV1cj45pOtUrR3vZTBwqcW8XA==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-my-way@8.1.0: @@ -1112,14 +1101,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.4.0: - resolution: {integrity: sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==} + globals@15.9.0: + resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} engines: {node: '>=18'} - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1156,6 +1141,10 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1334,8 +1323,8 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -1349,8 +1338,8 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} minimist-options@4.1.0: @@ -1367,8 +1356,8 @@ packages: module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} msgpack-lite@0.1.26: resolution: {integrity: sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==} @@ -1391,15 +1380,11 @@ packages: resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true - nodemon@3.1.3: - resolution: {integrity: sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==} + nodemon@3.1.4: + resolution: {integrity: sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==} engines: {node: '>=10'} hasBin: true - nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true - normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -1425,8 +1410,8 @@ packages: resolution: {integrity: sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==} engines: {node: '>=0.10'} - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} p-limit@2.3.0: @@ -1474,10 +1459,6 @@ packages: path-to-regexp@0.1.8: resolution: {integrity: sha512-EErxvEqTuliG5GCVHNt3K3UmfKhlOM26QtiJZ6XBnZgCd7n+P5aHNV37wFHGJSpbjN4danT+1CpOFT4giETmRQ==} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - pbf@3.2.1: resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==} hasBin: true @@ -1509,8 +1490,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.3.1: - resolution: {integrity: sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true @@ -1662,6 +1643,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} @@ -1684,10 +1670,6 @@ packages: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - slice-source@0.4.1: resolution: {integrity: sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==} @@ -1788,8 +1770,8 @@ packages: resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} engines: {node: '>=12'} - touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true tree-kill@1.2.2: @@ -1831,26 +1813,25 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@7.12.0: - resolution: {integrity: sha512-D6HKNbQcnNu3BaN4HkQCR16tgG8Q2AMUWPgvhrJksOXu+d6ys07yC06ONiV2kcsEfWC22voB6C3PvK2MqlBZ7w==} - engines: {node: ^18.18.0 || >=20.0.0} + typescript-eslint@8.4.0: + resolution: {integrity: sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} hasBin: true undefsafe@2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1870,6 +1851,10 @@ packages: engines: {node: '>= 8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -1906,8 +1891,6 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@aws-crypto/crc32@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 @@ -2459,17 +2442,17 @@ snapshots: '@datadog/sketches-js@2.1.1': {} - '@eslint-community/eslint-utils@4.4.0(eslint@9.4.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.9.1)': dependencies: - eslint: 9.4.0 + eslint: 9.9.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.11.0': {} - '@eslint/config-array@0.15.1': + '@eslint/config-array@0.18.0': dependencies: - '@eslint/object-schema': 2.1.3 - debug: 4.3.4(supports-color@5.5.0) + '@eslint/object-schema': 2.1.4 + debug: 4.3.7(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -2477,10 +2460,10 @@ snapshots: '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@5.5.0) - espree: 10.0.1 + debug: 4.3.7(supports-color@5.5.0) + espree: 10.1.0 globals: 14.0.0 - ignore: 5.3.1 + ignore: 5.3.2 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -2488,9 +2471,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.4.0': {} + '@eslint/js@9.9.1': {} - '@eslint/object-schema@2.1.3': {} + '@eslint/object-schema@2.1.4': {} '@fastify/accept-negotiator@1.1.0': {} @@ -2913,112 +2896,110 @@ snapshots: '@types/minimist@1.2.5': {} - '@types/node@20.14.2': + '@types/node@22.5.4': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/normalize-package-data@2.4.4': {} '@types/pbf@3.0.5': {} - '@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.4.0(@typescript-eslint/parser@8.4.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)': dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/type-utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.12.0 - eslint: 9.4.0 + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 8.4.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/scope-manager': 8.4.0 + '@typescript-eslint/type-utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.4.0 + eslint: 9.9.1 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5)': + '@typescript-eslint/parser@8.4.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.12.0 - debug: 4.3.4(supports-color@5.5.0) - eslint: 9.4.0 + '@typescript-eslint/scope-manager': 8.4.0 + '@typescript-eslint/types': 8.4.0 + '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.4.0 + debug: 4.3.7(supports-color@5.5.0) + eslint: 9.9.1 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.12.0': + '@typescript-eslint/scope-manager@8.4.0': dependencies: - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/visitor-keys': 7.12.0 + '@typescript-eslint/types': 8.4.0 + '@typescript-eslint/visitor-keys': 8.4.0 - '@typescript-eslint/type-utils@7.12.0(eslint@9.4.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@8.4.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@5.5.0) - eslint: 9.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) + debug: 4.3.7(supports-color@5.5.0) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: + - eslint - supports-color - '@typescript-eslint/types@7.12.0': {} + '@typescript-eslint/types@8.4.0': {} - '@typescript-eslint/typescript-estree@7.12.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@8.4.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/visitor-keys': 7.12.0 - debug: 4.3.4(supports-color@5.5.0) - globby: 11.1.0 + '@typescript-eslint/types': 8.4.0 + '@typescript-eslint/visitor-keys': 8.4.0 + debug: 4.3.7(supports-color@5.5.0) + fast-glob: 3.3.2 is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.12.0(eslint@9.4.0)(typescript@5.4.5)': + '@typescript-eslint/utils@8.4.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) - '@typescript-eslint/scope-manager': 7.12.0 - '@typescript-eslint/types': 7.12.0 - '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) - eslint: 9.4.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) + '@typescript-eslint/scope-manager': 8.4.0 + '@typescript-eslint/types': 8.4.0 + '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) + eslint: 9.9.1 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.12.0': + '@typescript-eslint/visitor-keys@8.4.0': dependencies: - '@typescript-eslint/types': 7.12.0 + '@typescript-eslint/types': 8.4.0 eslint-visitor-keys: 3.4.3 - abbrev@1.1.1: {} - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 abstract-logging@2.0.1: {} - acorn-import-attributes@1.9.5(acorn@8.11.3): + acorn-import-attributes@1.9.5(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn@8.11.3: {} + acorn@8.12.1: {} ajv-formats@2.1.1(ajv@8.12.0): optionalDependencies: @@ -3059,8 +3040,6 @@ snapshots: array-source@0.0.4: {} - array-union@2.1.0: {} - arrify@1.0.1: {} atomic-sleep@1.0.0: {} @@ -3069,7 +3048,7 @@ snapshots: dependencies: '@fastify/error': 3.4.1 archy: 1.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.7(supports-color@5.5.0) fastq: 1.17.1 transitivePeerDependencies: - supports-color @@ -3091,9 +3070,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 buffer-from@1.1.2: {} @@ -3126,7 +3105,7 @@ snapshots: chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -3231,9 +3210,9 @@ snapshots: shell-quote: 1.8.1 tlhunter-sorted-set: 0.1.0 - debug@4.3.4(supports-color@5.5.0): + debug@4.3.7(supports-color@5.5.0): dependencies: - ms: 2.1.2 + ms: 2.1.3 optionalDependencies: supports-color: 5.5.0 @@ -3250,10 +3229,6 @@ snapshots: detect-newline@3.1.0: {} - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - dotenv@16.4.5: {} duplexify@3.7.1: @@ -3286,7 +3261,7 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-scope@8.0.1: + eslint-scope@8.0.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3295,31 +3270,31 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint@9.4.0: + eslint@9.9.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/config-array': 0.15.1 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.18.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.4.0 + '@eslint/js': 9.9.1 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.7(supports-color@5.5.0) escape-string-regexp: 4.0.0 - eslint-scope: 8.0.1 + eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 - espree: 10.0.1 - esquery: 1.5.0 + espree: 10.1.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - ignore: 5.3.1 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -3328,19 +3303,19 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: - supports-color - espree@10.0.1: + espree@10.1.0: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 4.0.0 - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -3370,7 +3345,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} @@ -3433,7 +3408,7 @@ snapshots: dependencies: stream-source: 0.3.5 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -3487,16 +3462,7 @@ snapshots: globals@14.0.0: {} - globals@15.4.0: {} - - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 + globals@15.9.0: {} graphemer@1.4.0: {} @@ -3522,6 +3488,8 @@ snapshots: ignore@5.3.1: {} + ignore@5.3.2: {} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -3529,8 +3497,8 @@ snapshots: import-in-the-middle@1.8.0: dependencies: - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) cjs-module-lexer: 1.3.1 module-details-from-path: 1.0.3 @@ -3670,9 +3638,9 @@ snapshots: methods@1.1.2: {} - micromatch@4.0.5: + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -3683,7 +3651,7 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@9.0.4: + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -3701,7 +3669,7 @@ snapshots: module-details-from-path@1.0.3: {} - ms@2.1.2: {} + ms@2.1.3: {} msgpack-lite@0.1.26: dependencies: @@ -3720,23 +3688,19 @@ snapshots: node-gyp-build@4.8.1: {} - nodemon@3.1.3: + nodemon@3.1.4: dependencies: chokidar: 3.6.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.7(supports-color@5.5.0) ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.6.2 + semver: 7.6.3 simple-update-notifier: 2.0.0 supports-color: 5.5.0 - touch: 3.1.0 + touch: 3.1.1 undefsafe: 2.0.5 - nopt@1.0.10: - dependencies: - abbrev: 1.1.1 - normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -3763,14 +3727,14 @@ snapshots: opentracing@0.14.7: {} - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 p-limit@2.3.0: dependencies: @@ -3814,8 +3778,6 @@ snapshots: path-to-regexp@0.1.8: {} - path-type@4.0.0: {} - pbf@3.2.1: dependencies: ieee754: 1.2.1 @@ -3856,7 +3818,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.3.1: {} + prettier@3.3.3: {} process-nextick-args@2.0.1: {} @@ -3876,7 +3838,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.14.2 + '@types/node': 22.5.4 long: 5.2.3 protocol-buffers-schema@3.6.0: {} @@ -4009,6 +3971,8 @@ snapshots: semver@7.6.2: {} + semver@7.6.3: {} + set-cookie-parser@2.6.0: {} shapefile@0.6.6: @@ -4030,9 +3994,7 @@ snapshots: simple-update-notifier@2.0.0: dependencies: - semver: 7.6.2 - - slash@3.0.0: {} + semver: 7.6.3 slice-source@0.4.1: {} @@ -4125,17 +4087,15 @@ snapshots: toad-cache@3.7.0: {} - touch@3.1.0: - dependencies: - nopt: 1.0.10 + touch@3.1.1: {} tree-kill@1.2.2: {} trim-newlines@3.0.1: {} - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: - typescript: 5.4.5 + typescript: 5.5.4 tslib@1.14.1: {} @@ -4153,22 +4113,22 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@7.12.0(eslint@9.4.0)(typescript@5.4.5): + typescript-eslint@8.4.0(eslint@9.9.1)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 7.12.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5) - eslint: 9.4.0 + '@typescript-eslint/eslint-plugin': 8.4.0(@typescript-eslint/parser@8.4.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/parser': 8.4.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: + - eslint - supports-color - typescript@5.4.5: {} + typescript@5.5.4: {} undefsafe@2.0.5: {} - undici-types@5.26.5: {} + undici-types@6.19.8: {} uri-js@4.4.1: dependencies: @@ -4187,6 +4147,8 @@ snapshots: dependencies: isexe: 2.0.0 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 0000000..c372ae0 --- /dev/null +++ b/src/env.ts @@ -0,0 +1,17 @@ +/** + * Node's behavior is a bit weird with ES module imports. If this code is included inline in + * `server.ts`, it doesn't get run in time; the code in `server.ts` runs first (unclear why) before + * the environment variables are set up, and crashes. However, if this code is executed as the body + * of an import, everything is fine. :shrug: + */ + +import dotenv from 'dotenv'; + +switch (process.env.NODE_ENV) { + case 'development': + dotenv.config(); + break; + case 'test': + dotenv.config({path: '.test.env'}); + break; +} diff --git a/src/fetchTileData.ts b/src/fetchTileData.ts index cc388de..1544a8e 100644 --- a/src/fetchTileData.ts +++ b/src/fetchTileData.ts @@ -2,7 +2,7 @@ import fnv1a from '@sindresorhus/fnv1a'; import {LRUCache} from 'lru-cache'; -import {fastify} from './server.js'; +import {server} from './server.js'; // Generic type for a function that somehow fetches a tile and produces a `Buffer`, e.g., // `s3Fetcher` fetches a tile from an S3 bucket. @@ -39,7 +39,7 @@ export const interval = setInterval( const evictionRate = accesses > 0 ? evictions / accesses : 0; const fillPercentage = cache.calculatedSize / cache.maxSize; - fastify.log.info({lruCacheStats: {fillPercentage, hitRate, evictionRate}}); + server.log.info({lruCacheStats: {fillPercentage, hitRate, evictionRate}}); // Reset stats each interval. Maybe @TODO: total stats? hits = misses = evictions = 0; diff --git a/src/s3Fetcher.ts b/src/s3Fetcher.ts index fffd2fa..ed9682a 100644 --- a/src/s3Fetcher.ts +++ b/src/s3Fetcher.ts @@ -1,6 +1,6 @@ import {GetObjectCommand, S3Client} from '@aws-sdk/client-s3'; import {BAD_TILE, TILE_MISSING} from './fetchTileData.js'; -import {fastify} from './server.js'; +import {server} from './server.js'; const s3Client = new S3Client({region: process.env.AWS_REGION}); @@ -12,7 +12,7 @@ let stdDev = 0; export const interval = setInterval( () => { if (mean === 0) return; - fastify.log.info({s3Stats: {n, mean, stdDev}}); + server.log.info({s3Stats: {n, mean, stdDev}}); }, 1_000 * 60 * 5, ); @@ -44,7 +44,7 @@ export async function s3Fetcher(Bucket: string, Key: string): Promise { if (stdDev > 0) { const z = (ms - mean) / stdDev; if (z >= 2) { - fastify.log.info({ + server.log.info({ slowS3Request: {Bucket, Key, ms, z}, s3Stats: {n, mean, stdDev}, }); diff --git a/src/server.ts b/src/server.ts index df8f12b..cf8de21 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,4 @@ -import 'dotenv/config'; +import './env.js'; import compress from '@fastify/compress'; import cors from '@fastify/cors'; @@ -20,25 +20,24 @@ const unavailable = {Error: 'Elevation unavailable'}; const badRequest = {Error: 'Invalid request'}; const timeout = {Error: 'Request timed out'}; -export const fastify = Fastify({ +export const server = Fastify({ logger: true, ignoreTrailingSlash: true, disableRequestLogging: true, - // 500kb bodyLimit, connectionTimeout, keepAliveTimeout, }); // Add header for connection timeout to all responses -fastify.server.headersTimeout = connectionTimeout; +server.server.headersTimeout = connectionTimeout; /** * {@link https://fastify.dev/docs/latest/Reference/ContentTypeParser/#custom-parser-options | Fastify docs} * claim that `parseAs: 'buffer'` is the default, but it is not; this throws errors if not explicit. * The type signature for the `async` form of the handler is also incorrect or incomplete. */ -fastify.addContentTypeParser( +server.addContentTypeParser( 'application/x-protobuf', {parseAs: 'buffer'}, // @ts-expect-error type signature is incorrect or incomplete @@ -47,7 +46,7 @@ fastify.addContentTypeParser( }, ); -await fastify.register(cors, { +await server.register(cors, { origin: true, methods: ['GET', 'OPTIONS'], allowedHeaders: ['Origin', 'Content-Type', 'Content-Encoding', 'Accept'], @@ -58,27 +57,27 @@ await fastify.register(cors, { * {@link https://github.com/fastify/fastify-compress?tab=readme-ov-file#customtypes | customTypes} * _replaces_ the default types, so we must enumerate everything we want to support. */ -await fastify.register(compress, {customTypes: /^application\/(x-protobuf|x-terrarium-dem|json)$/}); +await server.register(compress, {customTypes: /^application\/(x-protobuf|x-terrarium-dem|json)$/}); -fastify.addHook('onTimeout', async (_request, reply) => { +server.addHook('onTimeout', async (_request, reply) => { reply.code(500); return timeout; }); -fastify.post('/geobuf', async (request, reply) => { +server.post('/geobuf', async (request, reply) => { try { const geoJson = request.body as GeoJSON; await addElevation(geoJson); reply.type('application/x-protobuf'); return geobuf.encode(geoJson, new Pbf()); } catch (error) { - fastify.log.error(error); + server.log.error(error); reply.code(500); return unavailable; } }); -fastify.post('/polyline', async (request, reply) => { +server.post('/polyline', async (request, reply) => { try { if (typeof request.body !== 'string') throw badRequest; reply.type('application/x-terrarium-dem'); @@ -88,14 +87,14 @@ fastify.post('/polyline', async (request, reply) => { reply.code(400); return badRequest; } else { - fastify.log.error(err); + server.log.error(err); reply.code(500); return unavailable; } } }); -fastify.post('/geojson', async (request, reply) => { +server.post('/geojson', async (request, reply) => { try { const geoJson = structuredClone(request.body); if (!isGeoJson(geoJson)) throw badRequest; @@ -106,18 +105,18 @@ fastify.post('/geojson', async (request, reply) => { reply.code(400); return badRequest; } else { - fastify.log.error(error); + server.log.error(error); reply.code(500); return unavailable; } } }); -fastify.get('/status', async (_request, reply) => reply.send({success: true})); +server.get('/status', async (_request, reply) => reply.send({success: true})); try { - await fastify.listen({port, host: '0.0.0.0'}); + await server.listen({port, host: '0.0.0.0'}); } catch (error) { - fastify.log.error(error); + server.log.error(error); process.exit(1); }