From d913a02a7c12b7c6409f58e313bf3c720a112491 Mon Sep 17 00:00:00 2001 From: apichick Date: Sun, 1 Jun 2025 13:26:16 +0200 Subject: [PATCH] Added multi-region API Gateway recipe, that was removed by accident (#3128) --- modules/api-gateway/README.md | 14 +- .../api-gateway/recipe-multi-region/README.md | 47 + .../recipe-multi-region/diagram.png | Bin 0 -> 53654 bytes .../recipe-multi-region/function/index.js | 7 + .../function/package-lock.json | 1439 +++++++++++++++++ .../recipe-multi-region/function/package.json | 17 + .../api-gateway/recipe-multi-region/main.tf | 152 ++ .../recipe-multi-region/outputs.tf | 20 + .../api-gateway/recipe-multi-region/spec.yaml | 35 + .../recipe-multi-region/variables.tf | 35 + 10 files changed, 1765 insertions(+), 1 deletion(-) create mode 100644 modules/api-gateway/recipe-multi-region/README.md create mode 100644 modules/api-gateway/recipe-multi-region/diagram.png create mode 100644 modules/api-gateway/recipe-multi-region/function/index.js create mode 100644 modules/api-gateway/recipe-multi-region/function/package-lock.json create mode 100644 modules/api-gateway/recipe-multi-region/function/package.json create mode 100644 modules/api-gateway/recipe-multi-region/main.tf create mode 100644 modules/api-gateway/recipe-multi-region/outputs.tf create mode 100644 modules/api-gateway/recipe-multi-region/spec.yaml create mode 100644 modules/api-gateway/recipe-multi-region/variables.tf diff --git a/modules/api-gateway/README.md b/modules/api-gateway/README.md index d3c16d38c..04b795c10 100644 --- a/modules/api-gateway/README.md +++ b/modules/api-gateway/README.md @@ -1,6 +1,16 @@ # API Gateway This module allows creating an API with its associated API config and API gateway. It also allows you grant IAM roles on the created resources. + +- [Examples](#examples) +- [Basic example](#basic-example) +- [Use existing service account](#use-existing-service-account) +- [Create service account](#create-service-account) +- [Recipes](#recipes) +- [Variables](#variables) +- [Outputs](#outputs) + + # Examples ## Basic example @@ -57,6 +67,9 @@ module "gateway" { # tftest modules=1 resources=11 inventory=create-sa.yaml ``` +## Recipes + +- [Multi-region deployment for API Gateway](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/blob/master/modules/api-gateway/recipe-multi-region) ## Variables @@ -85,5 +98,4 @@ module "gateway" { | [service_account](outputs.tf#L94) | Service account resource. | | | [service_account_email](outputs.tf#L99) | The service account for creating API configs. | | | [service_account_iam_email](outputs.tf#L104) | The service account for creating API configs. | | - diff --git a/modules/api-gateway/recipe-multi-region/README.md b/modules/api-gateway/recipe-multi-region/README.md new file mode 100644 index 000000000..152bb1bf8 --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/README.md @@ -0,0 +1,47 @@ +# Multi-region deployment for API Gateway + +This recipe shows you how to configure an HTTP(S) load balancer to enable multi-region deployments for API Gateway. For more details on how this set up work have a look at the article [here](https://cloud.google.com/api-gateway/docs/multi-region-deployment). + +The diagram below depicts the architecture that this blueprint sets up. + +![Architecture diagram](diagram.png) + +Once deployed do the following to see that it works: + +1. Copy the IP address returned as output + +2. Execute the following command: + + curl -k -v --resolve example.com:443: + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [project_id](variables.tf#L27) | Identifier of the project. | string | ✓ | | +| [regions](variables.tf#L32) | List of regions to deploy the proxy in. | list(string) | ✓ | | +| [_testing](variables.tf#L17) | Populate this variable to avoid triggering the data source. | object({…}) | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [address](outputs.tf#L17) | LB IP address. | | + +## Test + +```hcl +module "test" { + source = "./fabric/modules/api-gateway/recipe-multi-region" + project_id = "project-1" + regions = [ + "europe-west1", + "us-central1" + ] + _testing = { + name = "project-1" + number = 1234567890 + } +} +# tftest modules=8 resources=43 +``` diff --git a/modules/api-gateway/recipe-multi-region/diagram.png b/modules/api-gateway/recipe-multi-region/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..eb3f616023f502a42f179ccd60cdcc5409ca8878 GIT binary patch literal 53654 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 { + res.send('Hello World!'); +}); \ No newline at end of file diff --git a/modules/api-gateway/recipe-multi-region/function/package-lock.json b/modules/api-gateway/recipe-multi-region/function/package-lock.json new file mode 100644 index 000000000..2ba82adee --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/function/package-lock.json @@ -0,0 +1,1439 @@ +{ + "name": "function", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "function", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@google-cloud/functions-framework": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@google-cloud/functions-framework": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/functions-framework/-/functions-framework-4.0.0.tgz", + "integrity": "sha512-CNcYrz0/hw35Oq0D9RipHUB8KzH4ixq7o12L//qoOg0TFYv4953KrzCo0L2VP++19P39RShKTftDKMFmQhCeEw==", + "dependencies": { + "@types/express": "^4.17.21", + "body-parser": "1.20.3", + "cloudevents": "^8.0.2", + "express": "^4.21.2", + "minimist": "^1.2.8", + "on-finished": "^2.3.0", + "read-package-up": "^11.0.0", + "semver": "^7.7.1" + }, + "bin": { + "functions-framework": "build/src/main.js", + "functions-framework-nodejs": "build/src/main.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", + "integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/node": { + "version": "22.15.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", + "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", + "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cloudevents": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-8.0.3.tgz", + "integrity": "sha512-wTixKNjfLeyj9HQpESvLVVO4xgdqdvX4dTeg1IZ2SCunu/fxVzCamcIZneEyj31V82YolFCKwVeSkr8zResB0Q==", + "dependencies": { + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "json-bigint": "^1.0.0", + "process": "^0.11.10", + "util": "^0.12.4", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=16 <=22" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/index-to-position": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", + "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + } +} diff --git a/modules/api-gateway/recipe-multi-region/function/package.json b/modules/api-gateway/recipe-multi-region/function/package.json new file mode 100644 index 000000000..19080c2b5 --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/function/package.json @@ -0,0 +1,17 @@ +{ + "name": "function", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "engines": { + "node": ">=22.0.0" + }, + "dependencies": { + "@google-cloud/functions-framework": "^4.0.0" + } +} diff --git a/modules/api-gateway/recipe-multi-region/main.tf b/modules/api-gateway/recipe-multi-region/main.tf new file mode 100644 index 000000000..21b55b1dc --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/main.tf @@ -0,0 +1,152 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + api_id_prefix = "api" + function_name_prefix = "cf-hello" + specs = { for region in var.regions : region => + templatefile("${path.module}/spec.yaml", { + api_id = "${local.api_id_prefix}-${region}" + function_name = "${local.function_name_prefix}-${region}" + region = region + project_id = var.project_id + }) + } + backends = [ + for region in var.regions : { + backend = google_compute_region_network_endpoint_group.serverless-negs[region].id + } + ] +} + +resource "tls_private_key" "default" { + algorithm = "RSA" + rsa_bits = 2048 +} + +resource "tls_self_signed_cert" "default" { + private_key_pem = tls_private_key.default.private_key_pem + subject { + common_name = "example.com" + organization = "ACME Examples, Inc" + } + validity_period_hours = 720 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] +} + +module "project" { + source = "../../../modules/project" + name = var.project_id + project_reuse = { + use_data_source = var._testing == null + project_attributes = var._testing + } + services = [ + "apigateway.googleapis.com", + "cloudbuild.googleapis.com", + "cloudfunctions.googleapis.com", + "compute.googleapis.com", + "run.googleapis.com", + "servicemanagement.googleapis.com", + "servicecontrol.googleapis.com" + ] +} + +module "sa" { + source = "../../../modules/iam-service-account" + project_id = module.project.project_id + name = "sa-api" +} + + +module "functions" { + for_each = toset(var.regions) + source = "../../../modules/cloud-function-v2" + project_id = module.project.project_id + name = "${local.function_name_prefix}-${each.value}" + bucket_name = "bkt-${module.project.project_id}-${each.value}" + region = each.value + ingress_settings = "ALLOW_ALL" + bucket_config = { + location = null + lifecycle_delete_age_days = 1 + } + bundle_config = { + path = "${path.module}/function" + } + function_config = { + entry_point = "helloGET" + runtime = "nodejs22" + } + service_account_create = true + iam = { + "roles/run.invoker" = [module.sa.iam_email] + } +} + +module "gateways" { + for_each = toset(var.regions) + source = "../../../modules/api-gateway" + project_id = module.project.project_id + api_id = "${local.api_id_prefix}-${each.value}" + region = each.value + spec = local.specs[each.value] + service_account_email = module.sa.email +} + +module "glb" { + source = "../../../modules/net-lb-app-ext" + project_id = module.project.project_id + name = "glb" + use_classic_version = false + protocol = "HTTPS" + backend_service_configs = { + default = { + backends = local.backends + health_checks = [] + port_name = "" + } + } + ssl_certificates = { + create_configs = { + default = { + certificate = tls_self_signed_cert.default.cert_pem + private_key = tls_private_key.default.private_key_pem + } + } + } +} + +resource "google_compute_region_network_endpoint_group" "serverless-negs" { + for_each = toset(var.regions) + provider = google-beta + name = "serverless-neg-${module.gateways[each.value].gateway_id}" + project = module.project.project_id + network_endpoint_type = "SERVERLESS" + region = each.value + serverless_deployment { + platform = "apigateway.googleapis.com" + resource = module.gateways[each.value].gateway_id + url_mask = "" + } + lifecycle { + create_before_destroy = true + } +} diff --git a/modules/api-gateway/recipe-multi-region/outputs.tf b/modules/api-gateway/recipe-multi-region/outputs.tf new file mode 100644 index 000000000..b13d8073a --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/outputs.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "address" { + description = "LB IP address." + value = module.glb.address[""] +} diff --git a/modules/api-gateway/recipe-multi-region/spec.yaml b/modules/api-gateway/recipe-multi-region/spec.yaml new file mode 100644 index 000000000..2bae7f239 --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/spec.yaml @@ -0,0 +1,35 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +swagger: '2.0' +info: + title: ${api_id} Sample API + description: Sample API on API Gateway with a Google Cloud Functions backend + version: 1.0.0 +schemes: + - https +produces: + - application/json +paths: + /hello: + get: + summary: Greet a user + operationId: hello + x-google-backend: + address: https://${region}-${project_id}.cloudfunctions.net/${function_name} + responses: + '200': + description: A successful response + schema: + type: string \ No newline at end of file diff --git a/modules/api-gateway/recipe-multi-region/variables.tf b/modules/api-gateway/recipe-multi-region/variables.tf new file mode 100644 index 000000000..9905efe3b --- /dev/null +++ b/modules/api-gateway/recipe-multi-region/variables.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "_testing" { + description = "Populate this variable to avoid triggering the data source." + type = object({ + name = string + number = number + services_enabled = optional(list(string), []) + }) + default = null +} + +variable "project_id" { + description = "Identifier of the project." + type = string +} + +variable "regions" { + description = "List of regions to deploy the proxy in." + type = list(string) +} \ No newline at end of file