From e8fcaeb359aa0c410163290fb6460dcc56fd4aac Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 10:32:17 +0400 Subject: [PATCH 01/59] Build/Test Tools: Add Code Reference preview foundations The preview needs one checked-in source of truth for its toolchain, upstreams, runtime, limits, and behavioral smoke targets. Loose refs make the cache lie and make builds drift. Validate official repositories and full commits, resolve beta to a concrete versioned download, bind every material base input into the cache key, and keep arbitrary forks inert. Review follow-ups: move from Node 20 when the harness is exercised on a supported release; make cache-key field naming and ordering explicit when the build caller lands. --- .github/docs-playground-preview/.nvmrc | 1 + .../docs-playground-preview/dependencies.json | 73 + .../docs-playground-preview/package-lock.json | 3024 +++++++++++++++++ .github/docs-playground-preview/package.json | 16 + .../docs-playground-preview/lib/config.mjs | 177 + .../test/config.test.mjs | 158 + 6 files changed, 3449 insertions(+) create mode 100644 .github/docs-playground-preview/.nvmrc create mode 100644 .github/docs-playground-preview/dependencies.json create mode 100644 .github/docs-playground-preview/package-lock.json create mode 100644 .github/docs-playground-preview/package.json create mode 100644 .github/scripts/docs-playground-preview/lib/config.mjs create mode 100644 .github/scripts/docs-playground-preview/test/config.test.mjs diff --git a/.github/docs-playground-preview/.nvmrc b/.github/docs-playground-preview/.nvmrc new file mode 100644 index 0000000000000..ccc4c6c7f818a --- /dev/null +++ b/.github/docs-playground-preview/.nvmrc @@ -0,0 +1 @@ +20.20.2 diff --git a/.github/docs-playground-preview/dependencies.json b/.github/docs-playground-preview/dependencies.json new file mode 100644 index 0000000000000..b6653bfb49a40 --- /dev/null +++ b/.github/docs-playground-preview/dependencies.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "cacheSchemaVersion": 1, + "toolchain": { + "nodeVersion": "20.20.2", + "npmVersion": "10.8.2", + "composerVersion": "2.8.12" + }, + "playground": { + "cliVersion": "3.1.48", + "phpVersion": "8.4", + "wordpressChannel": "beta", + "wordpressVersionApi": "https://api.wordpress.org/core/version-check/1.7/?channel=beta", + "blueprintSchema": "https://playground.wordpress.net/blueprint-schema.json" + }, + "repositories": { + "phpdocParser": { + "repository": "WordPress/phpdoc-parser", + "commit": "1156399efccafd344818fa3b566ce5beafdc655e", + "path": "." + }, + "wporgDeveloper": { + "repository": "WordPress/wporg-developer", + "commit": "f2b6b9c1fe788fb4a5441a296b591f6dff540607", + "path": "source/wp-content/themes/wporg-developer-2023" + }, + "wporgParent2021": { + "repository": "WordPress/wporg-parent-2021", + "commit": "3b61f284dcc600dc5ad500e34d56108351909d32", + "path": "source/wp-content/themes/wporg-parent-2021" + }, + "wporgMuPlugins": { + "repository": "WordPress/wporg-mu-plugins", + "commit": "f37f522a0ed78b64748fa0b390e58e9f74de32ea", + "path": "mu-plugins" + }, + "postsToPosts": { + "repository": "scribu/wp-posts-to-posts", + "commit": "d2f297dbe257a09438da6ffe22c9a876acb7b49b", + "path": "." + }, + "codeSyntaxBlock": { + "repository": "mkaz/code-syntax-block", + "commit": "7179d747eef70ca8760cf5e0c04d3877158fa350", + "path": "." + } + }, + "limits": { + "snapshotBytes": 104857600, + "artifactRetentionDays": 1 + }, + "validation": { + "minimumSymbols": { + "classes": 400, + "methods": 3000, + "functions": 1200, + "hooks": 600, + "filters": 1000 + }, + "routes": { + "index": "/reference/", + "class": "/reference/classes/wp_html_tag_processor/", + "method": "/reference/classes/wp_html_tag_processor/next_tag/", + "function": "/reference/functions/wp_parse_args/", + "hook": "/reference/hooks/init/", + "filter": "/reference/hooks/the_content/" + }, + "search": { + "path": "/?s=wp_parse_args&post_type=wp-parser-function", + "expectedText": "wp_parse_args" + } + } +} diff --git a/.github/docs-playground-preview/package-lock.json b/.github/docs-playground-preview/package-lock.json new file mode 100644 index 0000000000000..2e6a587b8088a --- /dev/null +++ b/.github/docs-playground-preview/package-lock.json @@ -0,0 +1,3024 @@ +{ + "name": "wordpress-develop-code-reference-playground-preview", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wordpress-develop-code-reference-playground-preview", + "version": "1.0.0", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wp-playground/cli": "3.1.48" + }, + "engines": { + "node": "20.20.2" + } + }, + "node_modules/@nodable/entities": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz", + "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@octokit/app": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/app/-/app-14.1.0.tgz", + "integrity": "sha512-g3uEsGOQCBl1+W1rgfwoRFUIR6PtvB2T1E4RpygeUU5LrLvlOqcxrt5lfykIeRpUPpupreGJUYl70fqMDXdTpw==", + "license": "MIT", + "dependencies": { + "@octokit/auth-app": "^6.0.0", + "@octokit/auth-unauthenticated": "^5.0.0", + "@octokit/core": "^5.0.0", + "@octokit/oauth-app": "^6.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/types": "^12.0.0", + "@octokit/webhooks": "^12.0.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.1.4.tgz", + "integrity": "sha512-QkXkSOHZK4dA5oUqY5Dk3S+5pN2s1igPjEASNQV8/vgJgW034fQWR16u7VsNOK/EljA00eyjYF5mWNxWKWhHRQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^7.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "deprecation": "^2.3.1", + "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", + "universal-github-app-jwt": "^1.1.2", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz", + "integrity": "sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "@types/btoa-lite": "^1.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz", + "integrity": "sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz", + "integrity": "sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-unauthenticated": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz", + "integrity": "sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/oauth-app": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-6.1.0.tgz", + "integrity": "sha512-nIn/8eUJ/BKUVzxUXd5vpzl1rwaVxMyYbQkNZjHrF7Vk/yu98/YDF/N2KeWO7uZ0g3b5EyiFXFkZI8rJ+DH1/g==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^7.0.0", + "@octokit/auth-oauth-user": "^4.0.0", + "@octokit/auth-unauthenticated": "^5.0.0", + "@octokit/core": "^5.0.0", + "@octokit/oauth-authorization-url": "^6.0.2", + "@octokit/oauth-methods": "^4.0.0", + "@types/aws-lambda": "^8.10.83", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz", + "integrity": "sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz", + "integrity": "sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-authorization-url": "^6.0.2", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-graphql": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-4.0.1.tgz", + "integrity": "sha512-R8ZQNmrIKKpHWC6V2gum4x9LG2qF1RxRjo27gjQcG3j+vf2tLsEfE7I/wRWEPzYMaenr1M+qDAtNcwZve1ce1A==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz", + "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.2.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/webhooks": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-12.3.2.tgz", + "integrity": "sha512-exj1MzVXoP7xnAcAB3jZ97pTvVPkQF9y6GA/dvYC47HV7vLv+24XRS6b/v/XnyikpEuvMhugEXdGtAlU086WkQ==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/webhooks-methods": "^4.1.0", + "@octokit/webhooks-types": "7.6.1", + "aggregate-error": "^3.1.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz", + "integrity": "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", + "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", + "license": "MIT" + }, + "node_modules/@php-wasm/cli-util": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/cli-util/-/cli-util-3.1.48.tgz", + "integrity": "sha512-zNLQtNYVY9tFQEOQClFS6cNK+ntFq2HX0sPHb7HGRYPFV3vom1/Y42F7HQZBxUP+05N2VX0HL0csKlp41AGbeQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48", + "fast-xml-parser": "^5.8.0", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/logger": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-3.1.48.tgz", + "integrity": "sha512-BZdRRIs+Zc3IY3tme0KKsFOOtg/petabYftlXEHSFll/TKUEfOSV7GvMGKmF3tRkZFzadJzY9FClRV6kSIal4A==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-3.1.48.tgz", + "integrity": "sha512-VGe/ZmOmNJ9WjWOY9uApw7yEr+PS6mI9BVMVbUa/akWhZnloOD/J942izvFcaSUyn+UkYLOuFJkgY3ySulUtgw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/cli-util": "3.1.48", + "@php-wasm/logger": "3.1.48", + "@php-wasm/node-5-2": "3.1.48", + "@php-wasm/node-7-4": "3.1.48", + "@php-wasm/node-8-0": "3.1.48", + "@php-wasm/node-8-1": "3.1.48", + "@php-wasm/node-8-2": "3.1.48", + "@php-wasm/node-8-3": "3.1.48", + "@php-wasm/node-8-4": "3.1.48", + "@php-wasm/node-8-5": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "fs-ext-extra-prebuilt": "2.2.7", + "wasm-feature-detect": "1.8.0", + "ws": "8.21.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-5-2": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-5-2/-/node-5-2-3.1.48.tgz", + "integrity": "sha512-c3n+9Qs6vQv4haKRmihAmm/90D+r4TzSZcqd6maRXZbpmX2Mw3eymIpkQebRnW/LmOxOO7FC54/jmKHQZSmNQQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-7-4": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-7-4/-/node-7-4-3.1.48.tgz", + "integrity": "sha512-QzasgDrgbov6jkuokqB7yFtuP7SYXLwFZEighgb6HqcppAa3RAKHcsSsArDhhOKbu6NicmkjybdNrOKW9DuP7Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-0": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-0/-/node-8-0-3.1.48.tgz", + "integrity": "sha512-sGTAQdNp4URnBb8/b9IwbgdnC9Vh895JCY0lLS72lkWbrRgwvwsWyAY1iu38LnhHM1D+/xMhZj2wNbMvdPzzkg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-1": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-1/-/node-8-1-3.1.48.tgz", + "integrity": "sha512-sruxX5piVy0+9PBibFkgF+DEHGcPzOdCD2e7deLbYXMzLvOLGmqzMb4z7ng88WC6ZDk0Pk2jOTTq+08sG9BuMA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-2": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-2/-/node-8-2-3.1.48.tgz", + "integrity": "sha512-Dyp0SMyNee8FHFGed3KyyYiAGtHo9c2cFkJ/e3IdtX/+Uqo2pvFM8zcFLuWhwOiMJrEJPYl5FoXuER2H5pkHBw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-3": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-3/-/node-8-3-3.1.48.tgz", + "integrity": "sha512-vRlGi+Kd8jCfgtqGOZHriIp0ufyIMaVuPMGUbq99CKjvunyXouWE88Zn+lS/LQ7KTEhO86Xq4MEgzK1/huq4LA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-4": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-4/-/node-8-4-3.1.48.tgz", + "integrity": "sha512-TZfwQqdKYukMU5RXbTHgVx6YeiAlb7bN0NUVY5hDvMfioGNMnpBL0sWWf44ULj5L5TK39MbbYr0SQ7i5Rh2cyw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-5": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-5/-/node-8-5-3.1.48.tgz", + "integrity": "sha512-I3q1MKXjL2EfvpwC1PT2QiyLcPjOdvUVxP4x+8q94x2JMhtgH19lGMhxX9jnBjOGP8FAQ8cOcQ7JtxXQcWg9GQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/progress": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-3.1.48.tgz", + "integrity": "sha512-KFiI3Q9zDQ9NC7HGl5e/jx0BAvJYpyN1shv8vvJbeicXeuOoJnJS9C3XehRWlT9aRCIZ0qpeRSrmR3rR5ue0aQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/scopes": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-3.1.48.tgz", + "integrity": "sha512-3ncWvaCPs9gLyvskAplZdIMDyImT2MsJ8aRXrLMunvtjq1dwaPcCmvbzv1Z2czb2m23bxgTqalVn7jEDJbhlGw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/stream-compression": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-3.1.48.tgz", + "integrity": "sha512-bQzUn3gNAHcRUgkks5hrZc7jS+jirow+xORkMPsINobi+Y6j2za/OAaGMd9THo9298ubH6dGeeapZ5q58C0hsg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48" + } + }, + "node_modules/@php-wasm/universal": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-3.1.48.tgz", + "integrity": "sha512-CtopMuRcJwo8FVsmrzPhpvs/OsoGXYduHOemI78MSP/wfufosZcAg654J+d8IcF9xq6VTJjir3uxkE3t+bct4g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/util": "3.1.48", + "ini": "4.1.2" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/util": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-3.1.48.tgz", + "integrity": "sha512-MvHDY9K4ErSAOOAp5BypIX6ITTaYQugtbdcGR76ZCtjGCS91QBOe0Mm+75lfEOKnLOKltRdgUmfhV6Jb0oDZeg==", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/web-service-worker": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-3.1.48.tgz", + "integrity": "sha512-fMQLXvJLZxXM4cnPYbsihYVSxrkPhy3bI3gFwO5wJIv4J7WdsRFT5ddQSgpdJQ+u/ndwHZl4rTs0OTuEKYpy7w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/scopes": "3.1.48", + "@php-wasm/universal": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/xdebug-bridge": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/xdebug-bridge/-/xdebug-bridge-3.1.48.tgz", + "integrity": "sha512-P2PUgHHAAKs4Bd5EI6arWdojWt+Adw1QBYyotVgRq2z2+ICbUdvSAWiS5NwwFmLJq227vPsNHIgZftuVzhUmBQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/universal": "3.1.48", + "ws": "8.21.0", + "xml2js": "0.6.2", + "yargs": "17.7.2" + }, + "bin": { + "xdebug-bridge": "xdebug-bridge.js" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.162", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.162.tgz", + "integrity": "sha512-Fn658grtLOci1oxi1391vvDWJRKNGWRSqfxRkmN/Iy3c0tQH1USMKEXcPYHLvope+ZgTFocx9FRQJx1muBL6qw==", + "license": "MIT" + }, + "node_modules/@types/btoa-lite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", + "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==", + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@wp-playground/blueprints": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-3.1.48.tgz", + "integrity": "sha512-geJ1EdIWpRFxgnJrJqsYq+YUEJAFenKI6OCRRAfvgRAN+pei7HpCpSEnMcYB2atmpj6DtpqpKGlg3Yf1/EoRBA==", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@php-wasm/web-service-worker": "3.1.48", + "@wp-playground/common": "3.1.48", + "@wp-playground/storage": "3.1.48", + "@wp-playground/wordpress": "3.1.48", + "ajv": "8.18.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/cli": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/cli/-/cli-3.1.48.tgz", + "integrity": "sha512-24Y640IHzv7t/iEep1cUU5kZwUFTDXqljTRqOtddzQNByZzxL4g0zXSQYVUq6IPCh9rVx3/+elId/Ym6MCzRZA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/cli-util": "3.1.48", + "@php-wasm/logger": "3.1.48", + "@php-wasm/node": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@php-wasm/xdebug-bridge": "3.1.48", + "@wp-playground/blueprints": "3.1.48", + "@wp-playground/common": "3.1.48", + "@wp-playground/storage": "3.1.48", + "@wp-playground/tools": "3.1.48", + "@wp-playground/wordpress": "3.1.48", + "express": "4.22.2", + "fs-extra": "11.1.1", + "tmp-promise": "3.0.3", + "wasm-feature-detect": "1.8.0", + "yargs": "17.7.2" + }, + "bin": { + "wp-playground-cli": "wp-playground.js" + } + }, + "node_modules/@wp-playground/common": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-3.1.48.tgz", + "integrity": "sha512-+k7Ku33GWROchZmE0mP23aPTdCXxR7uZqsSgfpf+ttjuKB8uOI9TzfcqrRfSoLcqN2Rh7FAvJmtgbcgdOLfl+A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/storage": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-3.1.48.tgz", + "integrity": "sha512-5WMK4PpL5ETkoMsKPgLCwQ5b8Uz5PgFu0uvG+2tgSu7v8x2/GjuLsLloUl2vrPEu3ZrVDXrMOYnBiX8oEHcAPg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@zip.js/zip.js": "2.7.57", + "isomorphic-git": "1.37.6", + "octokit": "3.1.2", + "pako": "^1.0.10", + "sha.js": "2.4.12" + } + }, + "node_modules/@wp-playground/tools": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/tools/-/tools-3.1.48.tgz", + "integrity": "sha512-HnsBfBkMt7YrhO1d867uQg1OivEoPOKlAuEYwXkabv644O95hO5MrQQWv888qQIPHeKJKzXYjmGEL8KwCy9bGw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48", + "@wp-playground/blueprints": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/wordpress": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-3.1.48.tgz", + "integrity": "sha512-L0TSLNAoCXnHo9Ar4/0oTzM2OmJfhmQbko+ypf7EJhXILN73IsOhbAXp2MWfSUt24+rGGb6Z9BzlXmGPD6Brsw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@wp-playground/common": "3.1.48", + "zstddec": "^0.2.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@zip.js/zip.js": { + "version": "2.7.57", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.57.tgz", + "integrity": "sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA==", + "license": "BSD-3-Clause", + "engines": { + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=16.5.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "license": "Apache-2.0" + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "license": "MIT", + "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.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, + "node_modules/btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", + "license": "MIT" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "license": "Apache-2.0" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "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.15.1", + "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==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-builder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.0.tgz", + "integrity": "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.10.1.tgz", + "integrity": "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^3.0.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.1", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "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.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-ext-extra-prebuilt": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fs-ext-extra-prebuilt/-/fs-ext-extra-prebuilt-2.2.7.tgz", + "integrity": "sha512-Q7rayYRBDIvDF01HWOwSSjoaP+05N1g+o3BXL1Zf8Frw2JkjSmi4EtvCBITuW30l6hB2m2TW1pehdh8wyU/+gw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "nan": "^2.24.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unsafe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.0.tgz", + "integrity": "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isomorphic-git": { + "version": "1.37.6", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.37.6.tgz", + "integrity": "sha512-qr1NFCPsVTZ6YGqTXw0CzamnsHyH9QQ1OTEfeXIweSljRUMzuHFCJdUn0wc6OcjtTDns6knxjPb7N6LmJeftOA==", + "license": "MIT", + "dependencies": { + "async-lock": "^1.4.1", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^4.0.0", + "sha.js": "^2.4.12", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=14.17" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/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==", + "license": "MIT" + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "name": "@wolfy1339/lru-cache", + "version": "11.0.2-patch.1", + "resolved": "https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz", + "integrity": "sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==", + "license": "ISC", + "engines": { + "node": "18 >=18.20 || 20 || >=22" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", + "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/octokit": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/octokit/-/octokit-3.1.2.tgz", + "integrity": "sha512-MG5qmrTL5y8KYwFgE1A4JWmgfQBaIETE/lOlfwNYx1QOtCQHGVxkRJmdUJltFc1HVn73d61TlMhMyNTOtMl+ng==", + "license": "MIT", + "dependencies": { + "@octokit/app": "^14.0.2", + "@octokit/core": "^5.0.0", + "@octokit/oauth-app": "^6.0.0", + "@octokit/plugin-paginate-graphql": "^4.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0", + "@octokit/plugin-retry": "^6.0.0", + "@octokit/plugin-throttling": "^8.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "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" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "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==", + "license": "MIT", + "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==", + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "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.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz", + "integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/universal-github-app-jwt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.2.0.tgz", + "integrity": "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g==", + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "^9.0.0", + "jsonwebtoken": "^9.0.2" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "license": "ISC" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4.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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "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" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/zstddec": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.2.0.tgz", + "integrity": "sha512-oyPnDa1X5c13+Y7mA/FDMNJrn4S8UNBe0KCqtDmor40Re7ALrPN6npFwyYVRRh+PqozZQdeg23QtbcamZnG5rA==", + "license": "MIT AND BSD-3-Clause" + } + } +} diff --git a/.github/docs-playground-preview/package.json b/.github/docs-playground-preview/package.json new file mode 100644 index 0000000000000..e2e7db936c1ce --- /dev/null +++ b/.github/docs-playground-preview/package.json @@ -0,0 +1,16 @@ +{ + "name": "wordpress-develop-code-reference-playground-preview", + "version": "1.0.0", + "private": true, + "description": "Pinned tooling for the WordPress Core Code Reference Playground preview.", + "license": "GPL-2.0-or-later", + "engines": { + "node": "20.20.2" + }, + "scripts": { + "test": "node --test ../scripts/docs-playground-preview/test/*.test.mjs" + }, + "dependencies": { + "@wp-playground/cli": "3.1.48" + } +} diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs new file mode 100644 index 0000000000000..9f4e63ebe31ba --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -0,0 +1,177 @@ +import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; + +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const FULL_DIGEST = /^[0-9a-f]{64}$/; +const VERSION = /^\d+\.\d+\.\d+$/; +const API_BETA_VERSION = /^\d+\.\d+(?:\.\d+)?-(?:beta\d+|RC\d+)$/; +const OFFICIAL_REPOSITORIES = Object.freeze( { + phpdocParser: 'WordPress/phpdoc-parser', + wporgDeveloper: 'WordPress/wporg-developer', + wporgParent2021: 'WordPress/wporg-parent-2021', + wporgMuPlugins: 'WordPress/wporg-mu-plugins', + postsToPosts: 'scribu/wp-posts-to-posts', + codeSyntaxBlock: 'mkaz/code-syntax-block', +} ); +const DEPLOYMENT_REPOSITORIES = new Set( [ + 'WordPress/wordpress-develop', + 'sirreal/wordpress-develop', +] ); +const VERSION_API = + 'https://api.wordpress.org/core/version-check/1.7/?channel=beta'; + +function assertObject( value, label ) { + if ( ! value || typeof value !== 'object' || Array.isArray( value ) ) { + throw new Error( `${ label } must be an object.` ); + } +} + +function assertPositiveInteger( value, label ) { + if ( ! Number.isSafeInteger( value ) || value < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } +} + +function assertDigest( value, label ) { + if ( typeof value !== 'string' || ! FULL_DIGEST.test( value ) ) { + throw new Error( `${ label } must be a lowercase SHA-256 digest.` ); + } +} + +export function validateDependencies( dependencies ) { + assertObject( dependencies, 'Dependency manifest' ); + if ( dependencies.schemaVersion !== 1 ) { + throw new Error( `Unsupported dependency schema ${ dependencies.schemaVersion }.` ); + } + assertPositiveInteger( + dependencies.cacheSchemaVersion, + 'cacheSchemaVersion' + ); + assertObject( dependencies.toolchain, 'toolchain' ); + assertObject( dependencies.playground, 'playground' ); + for ( const name of [ 'nodeVersion', 'npmVersion', 'composerVersion' ] ) { + if ( ! VERSION.test( dependencies.toolchain[ name ] ) ) { + throw new Error( `toolchain.${ name } must be an exact version.` ); + } + } + if ( dependencies.playground.cliVersion !== '3.1.48' ) { + throw new Error( 'Unexpected Playground CLI version.' ); + } + if ( dependencies.playground.phpVersion !== '8.4' ) { + throw new Error( 'The Playground PHP version must be 8.4.' ); + } + if ( dependencies.playground.wordpressChannel !== 'beta' ) { + throw new Error( 'The WordPress runtime channel must be beta.' ); + } + if ( dependencies.playground.wordpressVersionApi !== VERSION_API ) { + throw new Error( 'The WordPress beta resolver must use the official API.' ); + } + if ( dependencies.limits?.snapshotBytes !== 104857600 ) { + throw new Error( 'The snapshot limit must be exactly 100 MiB.' ); + } + + assertObject( dependencies.repositories, 'repositories' ); + for ( const [ name, repository ] of Object.entries( + OFFICIAL_REPOSITORIES + ) ) { + const dependency = dependencies.repositories[ name ]; + assertObject( dependency, `repositories.${ name }` ); + if ( dependency.repository !== repository ) { + throw new Error( + `repositories.${ name } must use ${ repository }.` + ); + } + if ( ! FULL_COMMIT.test( dependency.commit ) ) { + throw new Error( + `repositories.${ name }.commit must be a full commit hash.` + ); + } + if ( typeof dependency.path !== 'string' || dependency.path === '' ) { + throw new Error( `repositories.${ name }.path must be nonempty.` ); + } + } + if ( + Object.keys( dependencies.repositories ).length !== + Object.keys( OFFICIAL_REPOSITORIES ).length + ) { + throw new Error( 'The dependency manifest contains an unknown repository.' ); + } + + assertObject( dependencies.validation?.minimumSymbols, 'minimumSymbols' ); + for ( const type of [ + 'classes', + 'methods', + 'functions', + 'hooks', + 'filters', + ] ) { + assertPositiveInteger( + dependencies.validation.minimumSymbols[ type ], + `minimumSymbols.${ type }` + ); + } + return dependencies; +} + +export async function loadDependencies( filename ) { + const bytes = await readFile( filename ); + const dependencies = validateDependencies( JSON.parse( bytes ) ); + return { + dependencies, + digest: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), + }; +} + +export async function resolveWordPressBeta( + fetchImplementation = globalThis.fetch +) { + const response = await fetchImplementation( VERSION_API, { + headers: { Accept: 'application/json' }, + } ); + if ( ! response.ok ) { + throw new Error( `WordPress beta API returned HTTP ${ response.status }.` ); + } + const body = await response.json(); + const offer = body?.offers?.find( + ( candidate ) => + API_BETA_VERSION.test( candidate?.version ) && + candidate.download === + `https://downloads.wordpress.org/release/wordpress-${ candidate.version }.zip` + ); + if ( ! offer ) { + throw new Error( 'The WordPress beta API returned no concrete beta build.' ); + } + return Object.freeze( { + channel: 'beta', + version: offer.version, + downloadUrl: offer.download, + } ); +} + +export function makeBaseCacheKey( inputs ) { + assertObject( inputs, 'Cache inputs' ); + assertPositiveInteger( inputs.schemaVersion, 'Cache schemaVersion' ); + for ( const [ name, value ] of Object.entries( { + platform: inputs.platform, + architecture: inputs.architecture, + phpVersion: inputs.phpVersion, + wordpressVersion: inputs.wordpressVersion, + } ) ) { + if ( typeof value !== 'string' || ! /^[A-Za-z0-9_.-]+$/.test( value ) ) { + throw new Error( `Cache ${ name } is invalid.` ); + } + } + assertDigest( inputs.dependencyDigest, 'Cache dependencyDigest' ); + assertDigest( inputs.harnessDigest, 'Cache harnessDigest' ); + const identity = createHash( 'sha256' ) + .update( JSON.stringify( inputs ) ) + .digest( 'hex' ); + return `docs-preview-base-v${ inputs.schemaVersion }-${ identity }`; +} + +export function isDeploymentEnabled( repository, stagingValue = '' ) { + return ( + DEPLOYMENT_REPOSITORIES.has( repository ) && + ( repository === 'WordPress/wordpress-develop' || stagingValue === 'true' ) + ); +} diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs new file mode 100644 index 0000000000000..c860c7892ebb6 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -0,0 +1,158 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; + +import { + isDeploymentEnabled, + makeBaseCacheKey, + resolveWordPressBeta, + validateDependencies, +} from '../lib/config.mjs'; + +const dependenciesFile = new URL( + '../../../docs-playground-preview/dependencies.json', + import.meta.url +); +const packageFile = new URL( + '../../../docs-playground-preview/package.json', + import.meta.url +); +const nodeVersionFile = new URL( + '../../../docs-playground-preview/.nvmrc', + import.meta.url +); + +async function manifest() { + return JSON.parse( await readFile( dependenciesFile, 'utf8' ) ); +} + +test( 'the checked-in dependency manifest is valid', async () => { + const dependencies = validateDependencies( await manifest() ); + const packageManifest = JSON.parse( await readFile( packageFile, 'utf8' ) ); + assert.equal( dependencies.schemaVersion, 1 ); + assert.equal( + ( await readFile( nodeVersionFile, 'utf8' ) ).trim(), + dependencies.toolchain.nodeVersion + ); + assert.equal( + packageManifest.engines.node, + dependencies.toolchain.nodeVersion + ); + assert.equal( + packageManifest.dependencies[ '@wp-playground/cli' ], + dependencies.playground.cliVersion + ); +} ); + +test( 'dependency repositories and commits are fixed', async () => { + const dependencies = await manifest(); + dependencies.repositories.phpdocParser.repository = 'attacker/parser'; + assert.throws( + () => validateDependencies( dependencies ), + /must use WordPress\/phpdoc-parser/ + ); + + const invalidCommit = await manifest(); + invalidCommit.repositories.wporgDeveloper.commit = 'trunk'; + assert.throws( + () => validateDependencies( invalidCommit ), + /must be a full commit hash/ + ); +} ); + +test( 'toolchain versions are exact and required', async () => { + for ( const name of [ 'nodeVersion', 'npmVersion', 'composerVersion' ] ) { + const dependencies = await manifest(); + delete dependencies.toolchain[ name ]; + assert.throws( + () => validateDependencies( dependencies ), + new RegExp( `toolchain\\.${ name } must be an exact version` ) + ); + } +} ); + +test( 'the beta resolver records a concrete official build', async () => { + const resolved = await resolveWordPressBeta( async ( url ) => { + assert.equal( + url, + 'https://api.wordpress.org/core/version-check/1.7/?channel=beta' + ); + return { + ok: true, + json: async () => ( { + offers: [ + { + response: 'development', + version: '7.2-beta1', + download: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + ], + } ), + }; + } ); + assert.deepEqual( resolved, { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + } ); +} ); + +test( 'the beta resolver rejects an unbound download URL', async () => { + await assert.rejects( + resolveWordPressBeta( async () => ( { + ok: true, + json: async () => ( { + offers: [ + { + response: 'autoupdate', + version: '7.2-beta1', + download: 'https://example.com/wordpress.zip', + }, + ], + } ), + } ) ), + /no concrete beta build/ + ); +} ); + +test( 'the cache key changes with every material base input', () => { + const inputs = { + schemaVersion: 1, + platform: 'linux', + architecture: 'x64', + phpVersion: '8.4', + wordpressVersion: '7.2-beta1', + dependencyDigest: 'a'.repeat( 64 ), + harnessDigest: 'b'.repeat( 64 ), + }; + const baseline = makeBaseCacheKey( inputs ); + for ( const [ name, value ] of Object.entries( { + platform: 'darwin', + architecture: 'arm64', + phpVersion: '8.5', + wordpressVersion: '7.2-beta2', + dependencyDigest: 'c'.repeat( 64 ), + harnessDigest: 'd'.repeat( 64 ), + } ) ) { + assert.notEqual( makeBaseCacheKey( { ...inputs, [ name ]: value } ), baseline ); + } +} ); + +test( 'deployment is inert outside the primary and opted-in staging repositories', () => { + assert.equal( isDeploymentEnabled( 'WordPress/wordpress-develop' ), true ); + assert.equal( isDeploymentEnabled( 'sirreal/wordpress-develop' ), false ); + assert.equal( + isDeploymentEnabled( 'sirreal/wordpress-develop', 'true' ), + true + ); + assert.equal( + isDeploymentEnabled( 'somebody/wordpress-develop', 'true' ), + false + ); + assert.equal( + isDeploymentEnabled( 'sirreal/wordpress-develop', 'TRUE' ), + false + ); +} ); From a80f03bbdc0fcf24c2244ac861fd0c3186764358 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 10:39:28 +0400 Subject: [PATCH 02/59] Build/Test Tools: Resolve Code Reference build inputs The base cache is only valid when every material input names the same build. Bind the runner, PHP version, concrete WordPress beta, dependency manifest, and harness into one exact key. Stage only eligible Core PHP as parser input. Fetch the pinned commit before every checkout; otherwise a reused clone breaks as soon as a dependency pin moves. --- .../docs-playground-preview/lib/config.mjs | 8 +- .../docs-playground-preview/lib/files.mjs | 144 ++++++++++++++++ .../docs-playground-preview/lib/inputs.mjs | 77 +++++++++ .../docs-playground-preview/lib/process.mjs | 45 +++++ .../test/config.test.mjs | 5 +- .../test/files.test.mjs | 155 ++++++++++++++++++ 6 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/lib/files.mjs create mode 100644 .github/scripts/docs-playground-preview/lib/inputs.mjs create mode 100644 .github/scripts/docs-playground-preview/lib/process.mjs create mode 100644 .github/scripts/docs-playground-preview/test/files.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index 9f4e63ebe31ba..72cfd4c5f36e9 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -150,10 +150,14 @@ export async function resolveWordPressBeta( export function makeBaseCacheKey( inputs ) { assertObject( inputs, 'Cache inputs' ); - assertPositiveInteger( inputs.schemaVersion, 'Cache schemaVersion' ); + assertPositiveInteger( + inputs.cacheSchemaVersion, + 'Cache cacheSchemaVersion' + ); for ( const [ name, value ] of Object.entries( { platform: inputs.platform, architecture: inputs.architecture, + runnerImage: inputs.runnerImage, phpVersion: inputs.phpVersion, wordpressVersion: inputs.wordpressVersion, } ) ) { @@ -166,7 +170,7 @@ export function makeBaseCacheKey( inputs ) { const identity = createHash( 'sha256' ) .update( JSON.stringify( inputs ) ) .digest( 'hex' ); - return `docs-preview-base-v${ inputs.schemaVersion }-${ identity }`; + return `docs-preview-base-v${ inputs.cacheSchemaVersion }-${ identity }`; } export function isDeploymentEnabled( repository, stagingValue = '' ) { diff --git a/.github/scripts/docs-playground-preview/lib/files.mjs b/.github/scripts/docs-playground-preview/lib/files.mjs new file mode 100644 index 0000000000000..d15ee7f60788e --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/files.mjs @@ -0,0 +1,144 @@ +import { createHash } from 'node:crypto'; +import { + copyFile, + mkdir, + readdir, + readFile, + rm, + stat, +} from 'node:fs/promises'; +import path from 'node:path'; + +import { run } from './process.mjs'; + +const EXCLUDED_SOURCE_DIRECTORIES = new Set( [ + 'wp-content/plugins', + 'wp-content/themes', +] ); + +export async function exists( filename ) { + try { + await stat( filename ); + return true; + } catch ( error ) { + if ( error.code === 'ENOENT' ) { + return false; + } + throw error; + } +} + +export async function findWordPressSourceRoot( candidate ) { + const root = path.resolve( candidate ); + for ( const directory of [ root, path.join( root, 'src' ) ] ) { + if ( await exists( path.join( directory, 'wp-includes/version.php' ) ) ) { + return directory; + } + } + throw new Error( `No WordPress source tree found beneath ${ root }.` ); +} + +async function listFiles( root, relative = '' ) { + const files = []; + const entries = await readdir( path.join( root, relative ), { + withFileTypes: true, + } ); + for ( const entry of entries.sort( ( a, b ) => a.name.localeCompare( b.name ) ) ) { + const child = relative ? `${ relative }/${ entry.name }` : entry.name; + if ( entry.isDirectory() ) { + files.push( ...( await listFiles( root, child ) ) ); + } else if ( entry.isFile() ) { + files.push( child ); + } + } + return files; +} + +export async function digestTree( root, include = () => true ) { + const hash = createHash( 'sha256' ); + for ( const relative of await listFiles( root ) ) { + if ( ! include( relative ) ) { + continue; + } + const bytes = await readFile( path.join( root, relative ) ); + hash.update( `${ Buffer.byteLength( relative ) }:${ relative }` ); + hash.update( `${ bytes.length }:` ); + hash.update( bytes ); + } + return hash.digest( 'hex' ); +} + +export async function sha256File( filename ) { + return createHash( 'sha256' ) + .update( await readFile( filename ) ) + .digest( 'hex' ); +} + +export async function stageCorePhp( candidate, destination ) { + const source = await findWordPressSourceRoot( candidate ); + await rm( destination, { recursive: true, force: true } ); + let count = 0; + for ( const relative of await listFiles( source ) ) { + if ( + ! relative.endsWith( '.php' ) || + [ ...EXCLUDED_SOURCE_DIRECTORIES ].some( + ( excluded ) => + relative === excluded || relative.startsWith( `${ excluded }/` ) + ) + ) { + continue; + } + const target = path.join( destination, relative ); + await mkdir( path.dirname( target ), { recursive: true } ); + await copyFile( path.join( source, relative ), target ); + count++; + } + if ( count === 0 ) { + throw new Error( 'The WordPress source tree contains no eligible PHP files.' ); + } + return { source, destination, files: count }; +} + +export async function acquireRepositories( + repositories, + destination, + runImplementation = run +) { + await mkdir( destination, { recursive: true } ); + const acquired = {}; + for ( const [ name, dependency ] of Object.entries( repositories ) ) { + const target = path.join( destination, name ); + if ( ! ( await exists( path.join( target, '.git' ) ) ) ) { + await rm( target, { recursive: true, force: true } ); + await runImplementation( + 'git', + [ + 'clone', + '--quiet', + '--no-checkout', + `https://github.com/${ dependency.repository }.git`, + target, + ], + { label: `clone ${ dependency.repository }` } + ); + } + await runImplementation( + 'git', + [ 'fetch', '--quiet', '--depth=1', 'origin', dependency.commit ], + { cwd: target, label: `fetch ${ dependency.repository }` } + ); + await runImplementation( + 'git', + [ + '-c', + 'advice.detachedHead=false', + 'checkout', + '--quiet', + dependency.commit, + ], + { cwd: target, label: `checkout ${ dependency.repository }` } + ); + acquired[ name ] = path.join( target, dependency.path ); + } + return acquired; +} diff --git a/.github/scripts/docs-playground-preview/lib/inputs.mjs b/.github/scripts/docs-playground-preview/lib/inputs.mjs new file mode 100644 index 0000000000000..7247f6f442232 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/inputs.mjs @@ -0,0 +1,77 @@ +import { createHash } from 'node:crypto'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import path from 'node:path'; + +import { + loadDependencies, + makeBaseCacheKey, + resolveWordPressBeta, +} from './config.mjs'; +import { digestTree } from './files.mjs'; + +export async function resolveBuildInputs( options ) { + const repositoryRoot = path.resolve( options.repositoryRoot ); + const configRoot = path.join( + repositoryRoot, + '.github/docs-playground-preview' + ); + const scriptsRoot = path.join( + repositoryRoot, + '.github/scripts/docs-playground-preview' + ); + const { dependencies, digest: dependencyDigest } = await loadDependencies( + path.join( configRoot, 'dependencies.json' ) + ); + const wordpress = await resolveWordPressBeta( options.fetchImplementation ); + const configDigest = await digestTree( + configRoot, + ( relative ) => ! relative.startsWith( 'node_modules/' ) + ); + const scriptsDigest = await digestTree( + scriptsRoot, + ( relative ) => ! relative.startsWith( 'test/' ) + ); + const harnessDigest = await digestTreePair( configDigest, scriptsDigest ); + const cacheInputs = { + cacheSchemaVersion: dependencies.cacheSchemaVersion, + platform: options.platform, + architecture: options.architecture, + runnerImage: options.runnerImage, + phpVersion: dependencies.playground.phpVersion, + wordpressVersion: wordpress.version, + dependencyDigest, + harnessDigest, + }; + const cacheKey = makeBaseCacheKey( cacheInputs ); + return { + schemaVersion: 1, + cacheKey, + cacheDirectory: path.join( path.resolve( options.cacheRoot ), cacheKey ), + cacheInputs, + dependencies, + wordpress, + }; +} + +async function digestTreePair( first, second ) { + return createHash( 'sha256' ) + .update( first ) + .update( second ) + .digest( 'hex' ); +} + +export async function writeResolvedInputs( inputs, filename ) { + await mkdir( path.dirname( filename ), { recursive: true } ); + await writeFile( filename, `${ JSON.stringify( inputs, null, 2 ) }\n` ); + if ( process.env.GITHUB_OUTPUT ) { + await writeFile( + process.env.GITHUB_OUTPUT, + `cache-key=${ inputs.cacheKey }\ncache-directory=${ inputs.cacheDirectory }\n`, + { flag: 'a' } + ); + } +} + +export async function readResolvedInputs( filename ) { + return JSON.parse( await readFile( filename, 'utf8' ) ); +} diff --git a/.github/scripts/docs-playground-preview/lib/process.mjs b/.github/scripts/docs-playground-preview/lib/process.mjs new file mode 100644 index 0000000000000..06cf8f6be69e1 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/process.mjs @@ -0,0 +1,45 @@ +import { spawn } from 'node:child_process'; +import { writeFile } from 'node:fs/promises'; + +export async function run( command, args, options = {} ) { + const capture = options.capture || Boolean( options.logFile ); + if ( ! options.quiet ) { + console.log( `$ ${ [ command, ...args ].join( ' ' ) }` ); + } + + return new Promise( ( resolve, reject ) => { + const child = spawn( command, args, { + cwd: options.cwd, + env: { ...process.env, ...options.env }, + stdio: capture ? [ 'ignore', 'pipe', 'pipe' ] : 'inherit', + } ); + let stdout = ''; + let stderr = ''; + child.stdout?.on( 'data', ( chunk ) => { + stdout += chunk; + } ); + child.stderr?.on( 'data', ( chunk ) => { + stderr += chunk; + } ); + child.once( 'error', reject ); + child.once( 'close', ( code, signal ) => { + ( async () => { + if ( options.logFile ) { + await writeFile( options.logFile, `${ stdout }${ stderr }` ); + } + const result = { code, signal, stdout, stderr }; + if ( code !== 0 && ! options.allowFailure ) { + const detail = `${ stdout }${ stderr }`.trim(); + throw new Error( + `${ options.label || command } failed${ + signal + ? ` with signal ${ signal }` + : ` with exit code ${ code }` + }${ detail ? `\n${ detail }` : '' }` + ); + } + return result; + } )().then( resolve, reject ); + } ); + } ); +} diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index c860c7892ebb6..3eb3461c06c26 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -119,9 +119,10 @@ test( 'the beta resolver rejects an unbound download URL', async () => { test( 'the cache key changes with every material base input', () => { const inputs = { - schemaVersion: 1, + cacheSchemaVersion: 1, platform: 'linux', architecture: 'x64', + runnerImage: 'ubuntu-24.04', phpVersion: '8.4', wordpressVersion: '7.2-beta1', dependencyDigest: 'a'.repeat( 64 ), @@ -129,8 +130,10 @@ test( 'the cache key changes with every material base input', () => { }; const baseline = makeBaseCacheKey( inputs ); for ( const [ name, value ] of Object.entries( { + cacheSchemaVersion: 2, platform: 'darwin', architecture: 'arm64', + runnerImage: 'macos-15', phpVersion: '8.5', wordpressVersion: '7.2-beta2', dependencyDigest: 'c'.repeat( 64 ), diff --git a/.github/scripts/docs-playground-preview/test/files.test.mjs b/.github/scripts/docs-playground-preview/test/files.test.mjs new file mode 100644 index 0000000000000..8ccb1d2a85bc5 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/files.test.mjs @@ -0,0 +1,155 @@ +import assert from 'node:assert/strict'; +import { mkdir, mkdtemp, readFile, symlink, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + acquireRepositories, + digestTree, + exists, + stageCorePhp, +} from '../lib/files.mjs'; +import { resolveBuildInputs } from '../lib/inputs.mjs'; +import { run } from '../lib/process.mjs'; + +const repositoryRoot = path.resolve( + path.dirname( new URL( import.meta.url ).pathname ), + '../../../..' +); + +test( 'run captures output and reports ordinary child failure', async () => { + const result = await run( + process.execPath, + [ '-e', 'process.stdout.write("ready")' ], + { capture: true, quiet: true } + ); + assert.equal( result.stdout, 'ready' ); + await assert.rejects( + run( process.execPath, [ '-e', 'process.stderr.write("broken");process.exit(2)' ], { + capture: true, + quiet: true, + } ), + /broken/ + ); +} ); + +test( 'stageCorePhp copies only eligible Core PHP source', async () => { + const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-source-' ) ); + const source = path.join( root, 'src' ); + for ( const relative of [ + 'wp-includes/version.php', + 'wp-admin/admin.php', + 'wp-content/plugins/hello.php', + 'wp-content/themes/twentytwenty/functions.php', + ] ) { + await mkdir( path.dirname( path.join( source, relative ) ), { + recursive: true, + } ); + await writeFile( path.join( source, relative ), ` { + const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-digest-' ) ); + await writeFile( path.join( root, 'a' ), 'one' ); + await writeFile( path.join( root, 'ignored' ), 'first' ); + const first = await digestTree( root, ( relative ) => relative !== 'ignored' ); + await writeFile( path.join( root, 'ignored' ), 'second' ); + assert.equal( + await digestTree( root, ( relative ) => relative !== 'ignored' ), + first + ); + await writeFile( path.join( root, 'a' ), 'two' ); + assert.notEqual( await digestTree( root ), first ); +} ); + +test( 'acquireRepositories uses Git with each validated full commit', async () => { + const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-repos-' ) ); + const calls = []; + const fakeRun = async ( command, args, options ) => { + calls.push( { command, args, options } ); + if ( args[ 0 ] === 'clone' ) { + await mkdir( path.join( args.at( -1 ), '.git' ), { recursive: true } ); + } + }; + const repositories = { + parser: { + repository: 'WordPress/phpdoc-parser', + commit: 'a'.repeat( 40 ), + path: '.', + }, + }; + const acquired = await acquireRepositories( repositories, root, fakeRun ); + assert.equal( acquired.parser, path.join( root, 'parser' ) ); + assert.deepEqual( calls[ 0 ].args.slice( 0, 3 ), [ + 'clone', + '--quiet', + '--no-checkout', + ] ); + assert.deepEqual( calls[ 1 ].args, [ + 'fetch', + '--quiet', + '--depth=1', + 'origin', + 'a'.repeat( 40 ), + ] ); + assert.equal( calls[ 2 ].args.at( -1 ), 'a'.repeat( 40 ) ); + + calls.length = 0; + repositories.parser.commit = 'b'.repeat( 40 ); + await acquireRepositories( repositories, root, fakeRun ); + assert.equal( calls.length, 2 ); + assert.equal( calls[ 0 ].args[ 0 ], 'fetch' ); + assert.equal( calls[ 0 ].args.at( -1 ), 'b'.repeat( 40 ) ); + assert.equal( calls[ 1 ].args.at( -1 ), 'b'.repeat( 40 ) ); +} ); + +test( 'resolveBuildInputs binds the concrete beta and runner to an exact cache', async () => { + const cacheRoot = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-cache-' ) ); + const fetchImplementation = async () => ( { + ok: true, + json: async () => ( { + offers: [ + { + response: 'development', + version: '7.2-beta1', + download: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + ], + } ), + } ); + const inputs = await resolveBuildInputs( { + repositoryRoot, + cacheRoot, + platform: 'linux', + architecture: 'x64', + runnerImage: 'ubuntu-24.04', + fetchImplementation, + } ); + assert.equal( inputs.wordpress.version, '7.2-beta1' ); + assert.match( inputs.cacheKey, /^docs-preview-base-v1-[0-9a-f]{64}$/ ); + assert.equal( inputs.cacheDirectory, path.join( cacheRoot, inputs.cacheKey ) ); +} ); From 4e27b0b7a48a0eead277ccaa446ceb5acfaa5e8b Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 10:44:17 +0400 Subject: [PATCH 03/59] Build/Test Tools: Pin Code Reference build tools The DevHub themes do not carry a complete immutable Node toolchain. Letting their ranges resolve at build time makes the invariant cache depend on the day it was built. Pin Yarn and the WordPress build packages in the central manifest and lock their dependency graph. A changed pin now changes the exact base-cache identity. --- .../docs-playground-preview/dependencies.json | 5 +- .../docs-playground-preview/package-lock.json | 24324 ++++++++++++++-- .github/docs-playground-preview/package.json | 5 +- .../docs-playground-preview/lib/config.mjs | 9 +- .../test/config.test.mjs | 21 +- 5 files changed, 22420 insertions(+), 1944 deletions(-) diff --git a/.github/docs-playground-preview/dependencies.json b/.github/docs-playground-preview/dependencies.json index b6653bfb49a40..b8ffebe75e70d 100644 --- a/.github/docs-playground-preview/dependencies.json +++ b/.github/docs-playground-preview/dependencies.json @@ -4,7 +4,10 @@ "toolchain": { "nodeVersion": "20.20.2", "npmVersion": "10.8.2", - "composerVersion": "2.8.12" + "composerVersion": "2.8.12", + "yarnVersion": "1.22.22", + "wpScriptsVersion": "32.6.0", + "wpI18nVersion": "6.24.0" }, "playground": { "cliVersion": "3.1.48", diff --git a/.github/docs-playground-preview/package-lock.json b/.github/docs-playground-preview/package-lock.json index 2e6a587b8088a..087ed80d5d889 100644 --- a/.github/docs-playground-preview/package-lock.json +++ b/.github/docs-playground-preview/package-lock.json @@ -9,2873 +9,23181 @@ "version": "1.0.0", "license": "GPL-2.0-or-later", "dependencies": { - "@wp-playground/cli": "3.1.48" + "@wordpress/i18n": "6.24.0", + "@wordpress/scripts": "32.6.0", + "@wp-playground/cli": "3.1.48", + "yarn": "1.22.22" }, "engines": { "node": "20.20.2" } }, - "node_modules/@nodable/entities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz", - "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/nodable" - } - ], - "license": "MIT" - }, - "node_modules/@octokit/app": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/app/-/app-14.1.0.tgz", - "integrity": "sha512-g3uEsGOQCBl1+W1rgfwoRFUIR6PtvB2T1E4RpygeUU5LrLvlOqcxrt5lfykIeRpUPpupreGJUYl70fqMDXdTpw==", + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", "license": "MIT", "dependencies": { - "@octokit/auth-app": "^6.0.0", - "@octokit/auth-unauthenticated": "^5.0.0", - "@octokit/core": "^5.0.0", - "@octokit/oauth-app": "^6.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/types": "^12.0.0", - "@octokit/webhooks": "^12.0.4" - }, - "engines": { - "node": ">= 18" + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" } }, - "node_modules/@octokit/auth-app": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.1.4.tgz", - "integrity": "sha512-QkXkSOHZK4dA5oUqY5Dk3S+5pN2s1igPjEASNQV8/vgJgW034fQWR16u7VsNOK/EljA00eyjYF5mWNxWKWhHRQ==", + "node_modules/@asamuzakjp/css-color/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==", + "license": "ISC" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-app": "^7.1.0", - "@octokit/auth-oauth-user": "^4.1.0", - "@octokit/request": "^8.3.1", - "@octokit/request-error": "^5.1.0", - "@octokit/types": "^13.1.0", - "deprecation": "^2.3.1", - "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", - "universal-github-app-jwt": "^1.1.2", - "universal-user-agent": "^6.0.0" + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" } }, - "node_modules/@octokit/auth-app/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@octokit/auth-app/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@octokit/auth-oauth-app": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz", - "integrity": "sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==", + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-device": "^6.1.0", - "@octokit/auth-oauth-user": "^4.1.0", - "@octokit/request": "^8.3.1", - "@octokit/types": "^13.0.0", - "@types/btoa-lite": "^1.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" + "ms": "^2.1.3" }, "engines": { - "node": ">= 18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "node_modules/@babel/core/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==", "license": "MIT" }, - "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@octokit/auth-oauth-device": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz", - "integrity": "sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==", + "node_modules/@babel/eslint-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "license": "MIT", "dependencies": { - "@octokit/oauth-methods": "^4.1.0", - "@octokit/request": "^8.3.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" }, "engines": { - "node": ">= 18" + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/auth-oauth-user": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz", - "integrity": "sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-device": "^6.1.0", - "@octokit/oauth-methods": "^4.1.0", - "@octokit/request": "^8.3.1", - "@octokit/types": "^13.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" + "@babel/types": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" } }, - "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" - }, - "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "license": "MIT", - "engines": { - "node": ">= 18" + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@octokit/auth-unauthenticated": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz", - "integrity": "sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "license": "MIT", "dependencies": { - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", - "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "license": "MIT", "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.1.0", - "@octokit/request": "^8.4.1", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "@babel/helper-annotate-as-pure": "^7.29.7", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@octokit/endpoint": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", - "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" + "ms": "^2.1.3" }, "engines": { - "node": ">= 18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "node_modules/@babel/helper-define-polyfill-provider/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==", "license": "MIT" }, - "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/graphql": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", - "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "license": "MIT", "dependencies": { - "@octokit/request": "^8.4.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" - }, - "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/oauth-app": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-6.1.0.tgz", - "integrity": "sha512-nIn/8eUJ/BKUVzxUXd5vpzl1rwaVxMyYbQkNZjHrF7Vk/yu98/YDF/N2KeWO7uZ0g3b5EyiFXFkZI8rJ+DH1/g==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "@octokit/auth-oauth-app": "^7.0.0", - "@octokit/auth-oauth-user": "^4.0.0", - "@octokit/auth-unauthenticated": "^5.0.0", - "@octokit/core": "^5.0.0", - "@octokit/oauth-authorization-url": "^6.0.2", - "@octokit/oauth-methods": "^4.0.0", - "@types/aws-lambda": "^8.10.83", - "universal-user-agent": "^6.0.0" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/oauth-authorization-url": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz", - "integrity": "sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" } }, - "node_modules/@octokit/oauth-methods": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz", - "integrity": "sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "license": "MIT", "dependencies": { - "@octokit/oauth-authorization-url": "^6.0.2", - "@octokit/request": "^8.3.1", - "@octokit/request-error": "^5.1.0", - "@octokit/types": "^13.0.0", - "btoa-lite": "^1.0.0" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/oauth-methods/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "node_modules/@octokit/oauth-methods/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "license": "MIT" + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@octokit/plugin-paginate-graphql": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-4.0.1.tgz", - "integrity": "sha512-R8ZQNmrIKKpHWC6V2gum4x9LG2qF1RxRjo27gjQcG3j+vf2tLsEfE7I/wRWEPzYMaenr1M+qDAtNcwZve1ce1A==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { - "node": ">= 18" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, - "peerDependencies": { - "@octokit/core": ">=5" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", - "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "license": "MIT", "dependencies": { - "@octokit/types": "^12.6.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" }, - "peerDependencies": { - "@octokit/core": "5" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", - "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "license": "MIT", "dependencies": { - "@octokit/types": "^12.6.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" }, "peerDependencies": { - "@octokit/core": "5" + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/plugin-retry": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", - "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "license": "MIT", "dependencies": { - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^13.0.0", - "bottleneck": "^2.15.3" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" }, "peerDependencies": { - "@octokit/core": "5" + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" - }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/plugin-throttling": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz", - "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==", + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "license": "MIT", "dependencies": { - "@octokit/types": "^12.2.0", - "bottleneck": "^2.15.3" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" }, "peerDependencies": { - "@octokit/core": "^5.0.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/request": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", - "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "license": "MIT", "dependencies": { - "@octokit/endpoint": "^9.0.6", - "@octokit/request-error": "^5.1.1", - "@octokit/types": "^13.1.0", - "universal-user-agent": "^6.0.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@octokit/request-error": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", - "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "license": "MIT", "dependencies": { - "@octokit/types": "^13.1.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "license": "MIT" + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@octokit/request/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^20.0.0" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@octokit/webhooks": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-12.3.2.tgz", - "integrity": "sha512-exj1MzVXoP7xnAcAB3jZ97pTvVPkQF9y6GA/dvYC47HV7vLv+24XRS6b/v/XnyikpEuvMhugEXdGtAlU086WkQ==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "license": "MIT", "dependencies": { - "@octokit/request-error": "^5.0.0", - "@octokit/webhooks-methods": "^4.1.0", - "@octokit/webhooks-types": "7.6.1", - "aggregate-error": "^3.1.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@octokit/webhooks-methods": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz", - "integrity": "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@octokit/webhooks-types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", - "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", - "license": "MIT" + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@php-wasm/cli-util": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/cli-util/-/cli-util-3.1.48.tgz", - "integrity": "sha512-zNLQtNYVY9tFQEOQClFS6cNK+ntFq2HX0sPHb7HGRYPFV3vom1/Y42F7HQZBxUP+05N2VX0HL0csKlp41AGbeQ==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", "dependencies": { - "@php-wasm/util": "3.1.48", - "fast-xml-parser": "^5.8.0", - "jsonc-parser": "3.3.1" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/logger": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-3.1.48.tgz", - "integrity": "sha512-BZdRRIs+Zc3IY3tme0KKsFOOtg/petabYftlXEHSFll/TKUEfOSV7GvMGKmF3tRkZFzadJzY9FClRV6kSIal4A==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-3.1.48.tgz", - "integrity": "sha512-VGe/ZmOmNJ9WjWOY9uApw7yEr+PS6mI9BVMVbUa/akWhZnloOD/J942izvFcaSUyn+UkYLOuFJkgY3ySulUtgw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", "dependencies": { - "@php-wasm/cli-util": "3.1.48", - "@php-wasm/logger": "3.1.48", - "@php-wasm/node-5-2": "3.1.48", - "@php-wasm/node-7-4": "3.1.48", - "@php-wasm/node-8-0": "3.1.48", - "@php-wasm/node-8-1": "3.1.48", - "@php-wasm/node-8-2": "3.1.48", - "@php-wasm/node-8-3": "3.1.48", - "@php-wasm/node-8-4": "3.1.48", - "@php-wasm/node-8-5": "3.1.48", - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48", - "fs-ext-extra-prebuilt": "2.2.7", - "wasm-feature-detect": "1.8.0", - "ws": "8.21.0" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-5-2": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-5-2/-/node-5-2-3.1.48.tgz", - "integrity": "sha512-c3n+9Qs6vQv4haKRmihAmm/90D+r4TzSZcqd6maRXZbpmX2Mw3eymIpkQebRnW/LmOxOO7FC54/jmKHQZSmNQQ==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-7-4": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-7-4/-/node-7-4-3.1.48.tgz", - "integrity": "sha512-QzasgDrgbov6jkuokqB7yFtuP7SYXLwFZEighgb6HqcppAa3RAKHcsSsArDhhOKbu6NicmkjybdNrOKW9DuP7Q==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-0": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-0/-/node-8-0-3.1.48.tgz", - "integrity": "sha512-sGTAQdNp4URnBb8/b9IwbgdnC9Vh895JCY0lLS72lkWbrRgwvwsWyAY1iu38LnhHM1D+/xMhZj2wNbMvdPzzkg==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-1": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-1/-/node-8-1-3.1.48.tgz", - "integrity": "sha512-sruxX5piVy0+9PBibFkgF+DEHGcPzOdCD2e7deLbYXMzLvOLGmqzMb4z7ng88WC6ZDk0Pk2jOTTq+08sG9BuMA==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-2": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-2/-/node-8-2-3.1.48.tgz", - "integrity": "sha512-Dyp0SMyNee8FHFGed3KyyYiAGtHo9c2cFkJ/e3IdtX/+Uqo2pvFM8zcFLuWhwOiMJrEJPYl5FoXuER2H5pkHBw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-3": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-3/-/node-8-3-3.1.48.tgz", - "integrity": "sha512-vRlGi+Kd8jCfgtqGOZHriIp0ufyIMaVuPMGUbq99CKjvunyXouWE88Zn+lS/LQ7KTEhO86Xq4MEgzK1/huq4LA==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-4": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-4/-/node-8-4-3.1.48.tgz", - "integrity": "sha512-TZfwQqdKYukMU5RXbTHgVx6YeiAlb7bN0NUVY5hDvMfioGNMnpBL0sWWf44ULj5L5TK39MbbYr0SQ7i5Rh2cyw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/node-8-5": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-5/-/node-8-5-3.1.48.tgz", - "integrity": "sha512-I3q1MKXjL2EfvpwC1PT2QiyLcPjOdvUVxP4x+8q94x2JMhtgH19lGMhxX9jnBjOGP8FAQ8cOcQ7JtxXQcWg9GQ==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "wasm-feature-detect": "1.8.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/progress": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-3.1.48.tgz", - "integrity": "sha512-KFiI3Q9zDQ9NC7HGl5e/jx0BAvJYpyN1shv8vvJbeicXeuOoJnJS9C3XehRWlT9aRCIZ0qpeRSrmR3rR5ue0aQ==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", "dependencies": { - "@php-wasm/logger": "3.1.48" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@php-wasm/scopes": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-3.1.48.tgz", - "integrity": "sha512-3ncWvaCPs9gLyvskAplZdIMDyImT2MsJ8aRXrLMunvtjq1dwaPcCmvbzv1Z2czb2m23bxgTqalVn7jEDJbhlGw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/stream-compression": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-3.1.48.tgz", - "integrity": "sha512-bQzUn3gNAHcRUgkks5hrZc7jS+jirow+xORkMPsINobi+Y6j2za/OAaGMd9THo9298ubH6dGeeapZ5q58C0hsg==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", + "license": "MIT", "dependencies": { - "@php-wasm/util": "3.1.48" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/universal": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-3.1.48.tgz", - "integrity": "sha512-CtopMuRcJwo8FVsmrzPhpvs/OsoGXYduHOemI78MSP/wfufosZcAg654J+d8IcF9xq6VTJjir3uxkE3t+bct4g==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", + "license": "MIT", "dependencies": { - "@php-wasm/logger": "3.1.48", - "@php-wasm/progress": "3.1.48", - "@php-wasm/stream-compression": "3.1.48", - "@php-wasm/util": "3.1.48", - "ini": "4.1.2" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/util": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-3.1.48.tgz", - "integrity": "sha512-MvHDY9K4ErSAOOAp5BypIX6ITTaYQugtbdcGR76ZCtjGCS91QBOe0Mm+75lfEOKnLOKltRdgUmfhV6Jb0oDZeg==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/web-service-worker": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-3.1.48.tgz", - "integrity": "sha512-fMQLXvJLZxXM4cnPYbsihYVSxrkPhy3bI3gFwO5wJIv4J7WdsRFT5ddQSgpdJQ+u/ndwHZl4rTs0OTuEKYpy7w==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", + "license": "MIT", "dependencies": { - "@php-wasm/scopes": "3.1.48", - "@php-wasm/universal": "3.1.48" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@php-wasm/xdebug-bridge": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@php-wasm/xdebug-bridge/-/xdebug-bridge-3.1.48.tgz", - "integrity": "sha512-P2PUgHHAAKs4Bd5EI6arWdojWt+Adw1QBYyotVgRq2z2+ICbUdvSAWiS5NwwFmLJq227vPsNHIgZftuVzhUmBQ==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", + "license": "MIT", "dependencies": { - "@php-wasm/logger": "3.1.48", - "@php-wasm/universal": "3.1.48", - "ws": "8.21.0", - "xml2js": "0.6.2", - "yargs": "17.7.2" - }, - "bin": { - "xdebug-bridge": "xdebug-bridge.js" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/aws-lambda": { - "version": "8.10.162", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.162.tgz", - "integrity": "sha512-Fn658grtLOci1oxi1391vvDWJRKNGWRSqfxRkmN/Iy3c0tQH1USMKEXcPYHLvope+ZgTFocx9FRQJx1muBL6qw==", - "license": "MIT" - }, - "node_modules/@types/btoa-lite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", - "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==", - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "license": "MIT", "dependencies": { - "@types/ms": "*", - "@types/node": "*" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", - "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "license": "MIT", "dependencies": { - "undici-types": "~8.3.0" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@wp-playground/blueprints": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-3.1.48.tgz", - "integrity": "sha512-geJ1EdIWpRFxgnJrJqsYq+YUEJAFenKI6OCRRAfvgRAN+pei7HpCpSEnMcYB2atmpj6DtpqpKGlg3Yf1/EoRBA==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", + "license": "MIT", "dependencies": { - "@php-wasm/logger": "3.1.48", - "@php-wasm/progress": "3.1.48", - "@php-wasm/stream-compression": "3.1.48", - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48", - "@php-wasm/web-service-worker": "3.1.48", - "@wp-playground/common": "3.1.48", - "@wp-playground/storage": "3.1.48", - "@wp-playground/wordpress": "3.1.48", - "ajv": "8.18.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@wp-playground/cli": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/cli/-/cli-3.1.48.tgz", - "integrity": "sha512-24Y640IHzv7t/iEep1cUU5kZwUFTDXqljTRqOtddzQNByZzxL4g0zXSQYVUq6IPCh9rVx3/+elId/Ym6MCzRZA==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", + "license": "MIT", "dependencies": { - "@php-wasm/cli-util": "3.1.48", - "@php-wasm/logger": "3.1.48", - "@php-wasm/node": "3.1.48", - "@php-wasm/progress": "3.1.48", - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48", - "@php-wasm/xdebug-bridge": "3.1.48", - "@wp-playground/blueprints": "3.1.48", - "@wp-playground/common": "3.1.48", - "@wp-playground/storage": "3.1.48", - "@wp-playground/tools": "3.1.48", - "@wp-playground/wordpress": "3.1.48", - "express": "4.22.2", - "fs-extra": "11.1.1", - "tmp-promise": "3.0.3", - "wasm-feature-detect": "1.8.0", - "yargs": "17.7.2" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, - "bin": { - "wp-playground-cli": "wp-playground.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@wp-playground/common": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-3.1.48.tgz", - "integrity": "sha512-+k7Ku33GWROchZmE0mP23aPTdCXxR7uZqsSgfpf+ttjuKB8uOI9TzfcqrRfSoLcqN2Rh7FAvJmtgbcgdOLfl+A==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", + "license": "MIT", "dependencies": { - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@wp-playground/storage": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-3.1.48.tgz", - "integrity": "sha512-5WMK4PpL5ETkoMsKPgLCwQ5b8Uz5PgFu0uvG+2tgSu7v8x2/GjuLsLloUl2vrPEu3ZrVDXrMOYnBiX8oEHcAPg==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", + "license": "MIT", "dependencies": { - "@php-wasm/stream-compression": "3.1.48", - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48", - "@zip.js/zip.js": "2.7.57", - "isomorphic-git": "1.37.6", - "octokit": "3.1.2", - "pako": "^1.0.10", - "sha.js": "2.4.12" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@wp-playground/tools": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/tools/-/tools-3.1.48.tgz", - "integrity": "sha512-HnsBfBkMt7YrhO1d867uQg1OivEoPOKlAuEYwXkabv644O95hO5MrQQWv888qQIPHeKJKzXYjmGEL8KwCy9bGw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", + "license": "MIT", "dependencies": { - "@php-wasm/util": "3.1.48", - "@wp-playground/blueprints": "3.1.48" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@wp-playground/wordpress": { - "version": "3.1.48", - "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-3.1.48.tgz", - "integrity": "sha512-L0TSLNAoCXnHo9Ar4/0oTzM2OmJfhmQbko+ypf7EJhXILN73IsOhbAXp2MWfSUt24+rGGb6Z9BzlXmGPD6Brsw==", - "license": "GPL-2.0-or-later", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", + "license": "MIT", "dependencies": { - "@php-wasm/logger": "3.1.48", - "@php-wasm/universal": "3.1.48", - "@php-wasm/util": "3.1.48", - "@wp-playground/common": "3.1.48", - "zstddec": "^0.2.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@zip.js/zip.js": { - "version": "2.7.57", - "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.57.tgz", - "integrity": "sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA==", - "license": "BSD-3-Clause", + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" + }, "engines": { - "bun": ">=0.7.0", - "deno": ">=1.0.0", - "node": ">=16.5.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=6.5" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/anynum": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", - "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/async-lock": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", - "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", - "license": "MIT" + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "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==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "license": "Apache-2.0" + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/body-parser": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", - "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.8.tgz", + "integrity": "sha512-6iSnEK0zlkLKU4heofK/AdmRD4e2SHVpJMtrwnTCzhnaM98ria4rTrOXBBi45BTTYnJtO8txnPsX4fChYXkmeA==", "license": "MIT", "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.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.15.1", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.8" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "license": "MIT" - }, - "node_modules/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", - "license": "MIT" - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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/@babel/plugin-transform-modules-umd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", - "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "get-intrinsic": "^1.3.0", - "set-function-length": "^1.2.2" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/clean-git-ref": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", - "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", - "license": "Apache-2.0" - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "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==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.29.7.tgz", + "integrity": "sha512-J0wGhKan+rIiE2OhfhRptySLrJ6SjQYM6b6N1FMlhyhCcw1Mig8vQjWchyB+bgHGDvaWo6Diu6CLRMra2uMtmg==", "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.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==", + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "license": "ISC" + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/diff3": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", - "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", - "license": "MIT" + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.8.tgz", + "integrity": "sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "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==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.7.tgz", + "integrity": "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==", "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "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==", + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.8.tgz", + "integrity": "sha512-4S9ksMGVWUshvgK0mKfvZky7leuG5/uoFVwMpAomJ8bMoDJiNHRVmc1EglwW/CmGVSqqWpEbXm9FmbRit22qoA==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" + }, "engines": { - "node": ">=0.8.x" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/express": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", - "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.5", - "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.15.1", - "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" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.10.0" + "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", - "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fast-xml-builder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.0.tgz", - "integrity": "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "license": "MIT", "dependencies": { - "path-expression-matcher": "^1.6.2", - "xml-naming": "^0.3.0" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fast-xml-parser": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.10.1.tgz", - "integrity": "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "license": "MIT", "dependencies": { - "@nodable/entities": "^3.0.0", - "fast-xml-builder": "^1.2.0", - "is-unsafe": "^2.0.0", - "path-expression-matcher": "^1.6.2", - "strnum": "^2.4.1", - "xml-naming": "^0.3.0" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, - "bin": { - "fxparser": "src/cli/cli.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "license": "MIT", "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.2", - "unpipe": "~1.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "node_modules/@babel/preset-env": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", "license": "MIT", "dependencies": { - "is-callable": "^1.2.7" + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/@babel/preset-react": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fs-ext-extra-prebuilt": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fs-ext-extra-prebuilt/-/fs-ext-extra-prebuilt-2.2.7.tgz", - "integrity": "sha512-Q7rayYRBDIvDF01HWOwSSjoaP+05N1g+o3BXL1Zf8Frw2JkjSmi4EtvCBITuW30l6hB2m2TW1pehdh8wyU/+gw==", - "hasInstallScript": true, + "node_modules/@babel/preset-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", "license": "MIT", "dependencies": { - "nan": "^2.24.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" }, "engines": { - "node": ">= 8.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">=14.14" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "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" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "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==", + "node_modules/@babel/traverse/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==", + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { - "node": ">= 0.4" + "node": ">=6.9.0" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "license": "MIT" + }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "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==", + "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "hashery": "^1.4.0", + "hookified": "^1.15.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" } }, - "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==", + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@keyv/serialize": "^1.1.1" } }, - "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==", + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "hashery": "^1.5.1", + "keyv": "^5.6.0" } }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "node_modules/@cacheable/utils/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" - }, + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, "engines": { - "node": ">= 0.8" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "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==", + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", "funding": [ { "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "url": "https://github.com/sponsors/csstools" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "opencollective", + "url": "https://opencollective.com/csstools" } ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.7.tgz", + "integrity": "sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", - "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", - "license": "ISC", + "node_modules/@csstools/media-query-list-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", + "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.1", + "@csstools/css-tokenizer": "^3.0.1" } }, - "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==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=10.0.0" } }, - "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==", + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", + "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", "license": "MIT", - "engines": { - "node": ">= 0.4" - }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/JounQin" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "license": "MIT", - "engines": { - "node": ">=8" + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" } }, - "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==", + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "license": "MIT", + "optional": true, "dependencies": { - "which-typed-array": "^1.1.16" + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.50.2", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz", + "integrity": "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.6", + "@typescript-eslint/types": "^8.11.0", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-plugin-eslint-comments": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.7.2.tgz", + "integrity": "sha512-LF03qURSwEWm2dz5wtdDCzNk+7Opl0X7q6I3undsaIuNsEiNvRV3BCtqu14Q/6Pzg1tBj44LcxpW2EpSLZStZw==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0", + "ignore": "^7.0.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@eslint-community/eslint-plugin-eslint-comments/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-2.1.0.tgz", + "integrity": "sha512-LgaSCymEpw7tF53xvDw9SNsraPb1IBHxpdABIOM0hW8UAlP8znrjYtuxfR58FSJ3L9BhwD+FaPRFQpZq84Nh6g==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "peerDependencies": { + "eslint": "^8.40 || 9 || 10" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/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==", + "license": "MIT", + "peer": true + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0", + "peer": true + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT", + "peer": true + }, + "node_modules/@eslint/eslintrc/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==", + "license": "MIT", + "peer": true + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz", + "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.2", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz", + "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/icu-skeleton-parser": "1.8.16", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz", + "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz", + "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@hapi/address": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", + "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/hoek": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/tlds": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.7.tgz", + "integrity": "sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/topo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.4.1.tgz", + "integrity": "sha512-dSlKrqug3siYNHVnjwIldShY12wAH3spwRltO/+8VOjg0X+xEq7vOs3DbBs4LRKsu7OH+NUb9kuZUNBF9Ho3TA==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", + "@types/jsdom": "^21.1.7", + "@types/node": "*", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/environment": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", + "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-mock": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/fake-timers": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", + "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@sinonjs/fake-timers": "^15.4.0", + "@types/node": "*", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/schemas": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/types": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", + "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.4.0", + "@jest/schemas": "30.4.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinclair/typebox": { + "version": "0.34.52", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", + "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", + "license": "MIT" + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinonjs/fake-timers": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", + "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-message-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", + "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.4.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-util": "30.4.1", + "picomatch": "^4.0.3", + "pretty-format": "30.4.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-mock": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", + "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", + "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/environment-jsdom-abstract/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", + "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern/node_modules/jest-regex-util": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", + "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "license": "MIT" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", + "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodable/entities": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz", + "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/app": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/app/-/app-14.1.0.tgz", + "integrity": "sha512-g3uEsGOQCBl1+W1rgfwoRFUIR6PtvB2T1E4RpygeUU5LrLvlOqcxrt5lfykIeRpUPpupreGJUYl70fqMDXdTpw==", + "license": "MIT", + "dependencies": { + "@octokit/auth-app": "^6.0.0", + "@octokit/auth-unauthenticated": "^5.0.0", + "@octokit/core": "^5.0.0", + "@octokit/oauth-app": "^6.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/types": "^12.0.0", + "@octokit/webhooks": "^12.0.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.1.4.tgz", + "integrity": "sha512-QkXkSOHZK4dA5oUqY5Dk3S+5pN2s1igPjEASNQV8/vgJgW034fQWR16u7VsNOK/EljA00eyjYF5mWNxWKWhHRQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^7.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "deprecation": "^2.3.1", + "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", + "universal-github-app-jwt": "^1.1.2", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz", + "integrity": "sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "@types/btoa-lite": "^1.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz", + "integrity": "sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz", + "integrity": "sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-unauthenticated": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz", + "integrity": "sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/oauth-app": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-6.1.0.tgz", + "integrity": "sha512-nIn/8eUJ/BKUVzxUXd5vpzl1rwaVxMyYbQkNZjHrF7Vk/yu98/YDF/N2KeWO7uZ0g3b5EyiFXFkZI8rJ+DH1/g==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^7.0.0", + "@octokit/auth-oauth-user": "^4.0.0", + "@octokit/auth-unauthenticated": "^5.0.0", + "@octokit/core": "^5.0.0", + "@octokit/oauth-authorization-url": "^6.0.2", + "@octokit/oauth-methods": "^4.0.0", + "@types/aws-lambda": "^8.10.83", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz", + "integrity": "sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz", + "integrity": "sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-authorization-url": "^6.0.2", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-graphql": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-4.0.1.tgz", + "integrity": "sha512-R8ZQNmrIKKpHWC6V2gum4x9LG2qF1RxRjo27gjQcG3j+vf2tLsEfE7I/wRWEPzYMaenr1M+qDAtNcwZve1ce1A==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz", + "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.2.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/webhooks": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-12.3.2.tgz", + "integrity": "sha512-exj1MzVXoP7xnAcAB3jZ97pTvVPkQF9y6GA/dvYC47HV7vLv+24XRS6b/v/XnyikpEuvMhugEXdGtAlU086WkQ==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/webhooks-methods": "^4.1.0", + "@octokit/webhooks-types": "7.6.1", + "aggregate-error": "^3.1.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz", + "integrity": "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", + "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", + "license": "MIT" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz", + "integrity": "sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.1.tgz", + "integrity": "sha512-ht7YGWQuV5BopMcw5Q2hXn3I8eG8TH0J/kc/GMcW4CuNTgiP6wCu44BOnucJWL3CmFWaRHI//vWyAhaC8BwePw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.1.tgz", + "integrity": "sha512-K/qU4CjnzOpNkkKO4DfCLSQshejRNAJtd4esgigo/50nxCB6XCyi1dhAblUHM9jG5dRm8eu0FB+t87nIo99LYQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.1.tgz", + "integrity": "sha512-QNXPTWteDclR2B4pDFpz0TNghgB33UMjUt14B+BZPmtH1MwUFAfLHBaP5If0Z5NZC+jaH8oF2glgYjrmhZWmSw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.1.tgz", + "integrity": "sha512-6g0FhB3B9UobAR60BGTcXg4IHZ6aaYJzp0Ki5FhnxyAPt8Ns+9SSvgcrnsN2eGmk3RWG5vYycUGOEApycQL24A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.1.tgz", + "integrity": "sha512-M6qGYsp1cURtvVLGDrPPZemMFEbuMmCXgQYTReC/IbimV5sGrLBjB+/hANUpRZjX67nGLdKSVLZuQQAiNz+sww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.1.tgz", + "integrity": "sha512-EGQRWMGqwiuVma8ZLAZnExQ7sBvbOx0N/AE/nlafISPs8S+QtXX+Viy6dcQwVWwYHQPAcuY3bFt3xgoAwb4ZNQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.2.tgz", + "integrity": "sha512-7Ehow/7Wp3aoyCrZwQpU7a2CnoMq0XhIcioFuKjBb0PLYfBfmTsFTUyatlHu0fRxhwcRsSQRTvEhmZu8CppBpQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.2.tgz", + "integrity": "sha512-1Uz5iJ9ZAlFOiPuwYg29Bf7bJJc/GeoeJIFKJYQf67nTVKFe8RHbEtxgkOmK4UGZNHKXcpW4P8cWBYzBn1USpg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.2", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.1.tgz", + "integrity": "sha512-OtFGSN+kgk/aoKgdkKQnBsQFDiG8WdCxu+UrHr0bXScdAmtSzLSraLo7wFIb25RVHfRWvzI5kZomqJYEg/l1iA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.1.tgz", + "integrity": "sha512-OtjaKs8H7oysfErajdYr1yuWSjMAectT7Dwr+axIoZqT9lmEOkD/H/3rgAs8h/NIuEi2imSXD+vL4MZtOuJfqQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.1.tgz", + "integrity": "sha512-U4dQxkNhvPexffjEmGwCq68FuftFK15JgUF05y/HlK3M6W/G2iEaACIfXdSnwVNe9Qh0sPfw8LbOPxrWzGWGMQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.1.tgz", + "integrity": "sha512-l/c+Z9F86cOiPJUllUCt09v+kICKvT+Vg1vOAJHtHPsJIzurGayucfCMq2acd/A/yxeNWunl9d9eqZ0G+XiI6A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.1.tgz", + "integrity": "sha512-5MPkYCvG2yw7WONEjYj5lr5JFehTobW7wX+ZUFy81oF2lr9IPfZk9qO+FTaM0bGEiymwfLwKe6jE15nHn1nmHg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.52.0.tgz", + "integrity": "sha512-1xmAqOtRUQGR7QfJFfGV/M2kC7wmI2WgZdpru8hJl3S0r4hW0n3OQpEHlSGXJAaNFyvT+ilnwkT+g5L4ljHR6g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.1.tgz", + "integrity": "sha512-3kINtW1LUTPkiXFRSSBmva1SXzS/72we/jL22N+BnF3DFcoewkdkHPYOIdAAk9gSicJ4d5Ojtt1/HeibEc5OQg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.1.tgz", + "integrity": "sha512-TKp4hQ8iKQsY7vnp/j0yJJ4ZsP109Ht6l4RHTj0lNEG1TfgTrIH5vJMbgmoYXWzNHAqBH2e7fncN12p3BP8LFg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.2.tgz", + "integrity": "sha512-h6Ad60FjCYdJZ5DTz1Lk2VmQsShiViKe0G7sYikb0GHI0NVvApp2XQNRHNjEMz87roFttGPLHOYVPlfy+yVIhQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.51.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.1.tgz", + "integrity": "sha512-QxgjSrxyWZc7Vk+qGSfsejPVFL1AgAJdSBMYZdDUbwg730D09ub3PXScB9d04vIqPriZ+0dqzjmQx0yWKiCi2Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.1.tgz", + "integrity": "sha512-UMqleEoabYMsWoTkqyt9WAzXwZ4BlFZHO40wr3d5ZvtjKCHlD4YXLm+6OLCeIi/HkX7EXvQaz8gtAwkwwSEvcQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.1.tgz", + "integrity": "sha512-5Cuy/nj0HBaH+ZJ4leuD7RjgvA844aY2WW+B5uLcWtxGjRZl3MNLuxnNg5DYWZNPO+NafSSnra0q49KWAHsKBg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.1.tgz", + "integrity": "sha512-rkOGikPEyRpMCmNu9AQuV5dtRlDmJp2dK5sw8roVshAGoB6hH/3QjDtRhdwd75SsJwgynWUNRUYe0wAkTo16tQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", + "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.6.0", + "@parcel/watcher-darwin-arm64": "2.6.0", + "@parcel/watcher-darwin-x64": "2.6.0", + "@parcel/watcher-freebsd-x64": "2.6.0", + "@parcel/watcher-linux-arm-glibc": "2.6.0", + "@parcel/watcher-linux-arm-musl": "2.6.0", + "@parcel/watcher-linux-arm64-glibc": "2.6.0", + "@parcel/watcher-linux-arm64-musl": "2.6.0", + "@parcel/watcher-linux-x64-glibc": "2.6.0", + "@parcel/watcher-linux-x64-musl": "2.6.0", + "@parcel/watcher-win32-arm64": "2.6.0", + "@parcel/watcher-win32-x64": "2.6.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz", + "integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz", + "integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz", + "integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz", + "integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz", + "integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz", + "integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz", + "integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz", + "integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz", + "integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz", + "integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz", + "integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz", + "integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@paulirish/trace_engine": { + "version": "0.0.59", + "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.59.tgz", + "integrity": "sha512-439NUzQGmH+9Y017/xCchBP9571J4bzhpcNhrxorf7r37wcyJZkgUfrUsRL3xl+JDcZ6ORhoFCzCw98c6S3YHw==", + "license": "BSD-3-Clause", + "dependencies": { + "legacy-javascript": "latest", + "third-party-web": "latest" + } + }, + "node_modules/@php-wasm/cli-util": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/cli-util/-/cli-util-3.1.48.tgz", + "integrity": "sha512-zNLQtNYVY9tFQEOQClFS6cNK+ntFq2HX0sPHb7HGRYPFV3vom1/Y42F7HQZBxUP+05N2VX0HL0csKlp41AGbeQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48", + "fast-xml-parser": "^5.8.0", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/logger": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-3.1.48.tgz", + "integrity": "sha512-BZdRRIs+Zc3IY3tme0KKsFOOtg/petabYftlXEHSFll/TKUEfOSV7GvMGKmF3tRkZFzadJzY9FClRV6kSIal4A==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-3.1.48.tgz", + "integrity": "sha512-VGe/ZmOmNJ9WjWOY9uApw7yEr+PS6mI9BVMVbUa/akWhZnloOD/J942izvFcaSUyn+UkYLOuFJkgY3ySulUtgw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/cli-util": "3.1.48", + "@php-wasm/logger": "3.1.48", + "@php-wasm/node-5-2": "3.1.48", + "@php-wasm/node-7-4": "3.1.48", + "@php-wasm/node-8-0": "3.1.48", + "@php-wasm/node-8-1": "3.1.48", + "@php-wasm/node-8-2": "3.1.48", + "@php-wasm/node-8-3": "3.1.48", + "@php-wasm/node-8-4": "3.1.48", + "@php-wasm/node-8-5": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "fs-ext-extra-prebuilt": "2.2.7", + "wasm-feature-detect": "1.8.0", + "ws": "8.21.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-5-2": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-5-2/-/node-5-2-3.1.48.tgz", + "integrity": "sha512-c3n+9Qs6vQv4haKRmihAmm/90D+r4TzSZcqd6maRXZbpmX2Mw3eymIpkQebRnW/LmOxOO7FC54/jmKHQZSmNQQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-7-4": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-7-4/-/node-7-4-3.1.48.tgz", + "integrity": "sha512-QzasgDrgbov6jkuokqB7yFtuP7SYXLwFZEighgb6HqcppAa3RAKHcsSsArDhhOKbu6NicmkjybdNrOKW9DuP7Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-0": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-0/-/node-8-0-3.1.48.tgz", + "integrity": "sha512-sGTAQdNp4URnBb8/b9IwbgdnC9Vh895JCY0lLS72lkWbrRgwvwsWyAY1iu38LnhHM1D+/xMhZj2wNbMvdPzzkg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-1": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-1/-/node-8-1-3.1.48.tgz", + "integrity": "sha512-sruxX5piVy0+9PBibFkgF+DEHGcPzOdCD2e7deLbYXMzLvOLGmqzMb4z7ng88WC6ZDk0Pk2jOTTq+08sG9BuMA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-2": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-2/-/node-8-2-3.1.48.tgz", + "integrity": "sha512-Dyp0SMyNee8FHFGed3KyyYiAGtHo9c2cFkJ/e3IdtX/+Uqo2pvFM8zcFLuWhwOiMJrEJPYl5FoXuER2H5pkHBw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-3": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-3/-/node-8-3-3.1.48.tgz", + "integrity": "sha512-vRlGi+Kd8jCfgtqGOZHriIp0ufyIMaVuPMGUbq99CKjvunyXouWE88Zn+lS/LQ7KTEhO86Xq4MEgzK1/huq4LA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-4": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-4/-/node-8-4-3.1.48.tgz", + "integrity": "sha512-TZfwQqdKYukMU5RXbTHgVx6YeiAlb7bN0NUVY5hDvMfioGNMnpBL0sWWf44ULj5L5TK39MbbYr0SQ7i5Rh2cyw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/node-8-5": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-5/-/node-8-5-3.1.48.tgz", + "integrity": "sha512-I3q1MKXjL2EfvpwC1PT2QiyLcPjOdvUVxP4x+8q94x2JMhtgH19lGMhxX9jnBjOGP8FAQ8cOcQ7JtxXQcWg9GQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "wasm-feature-detect": "1.8.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/progress": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-3.1.48.tgz", + "integrity": "sha512-KFiI3Q9zDQ9NC7HGl5e/jx0BAvJYpyN1shv8vvJbeicXeuOoJnJS9C3XehRWlT9aRCIZ0qpeRSrmR3rR5ue0aQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/scopes": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-3.1.48.tgz", + "integrity": "sha512-3ncWvaCPs9gLyvskAplZdIMDyImT2MsJ8aRXrLMunvtjq1dwaPcCmvbzv1Z2czb2m23bxgTqalVn7jEDJbhlGw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/stream-compression": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-3.1.48.tgz", + "integrity": "sha512-bQzUn3gNAHcRUgkks5hrZc7jS+jirow+xORkMPsINobi+Y6j2za/OAaGMd9THo9298ubH6dGeeapZ5q58C0hsg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48" + } + }, + "node_modules/@php-wasm/universal": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-3.1.48.tgz", + "integrity": "sha512-CtopMuRcJwo8FVsmrzPhpvs/OsoGXYduHOemI78MSP/wfufosZcAg654J+d8IcF9xq6VTJjir3uxkE3t+bct4g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/util": "3.1.48", + "ini": "4.1.2" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/util": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-3.1.48.tgz", + "integrity": "sha512-MvHDY9K4ErSAOOAp5BypIX6ITTaYQugtbdcGR76ZCtjGCS91QBOe0Mm+75lfEOKnLOKltRdgUmfhV6Jb0oDZeg==", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/web-service-worker": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-3.1.48.tgz", + "integrity": "sha512-fMQLXvJLZxXM4cnPYbsihYVSxrkPhy3bI3gFwO5wJIv4J7WdsRFT5ddQSgpdJQ+u/ndwHZl4rTs0OTuEKYpy7w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/scopes": "3.1.48", + "@php-wasm/universal": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@php-wasm/xdebug-bridge": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@php-wasm/xdebug-bridge/-/xdebug-bridge-3.1.48.tgz", + "integrity": "sha512-P2PUgHHAAKs4Bd5EI6arWdojWt+Adw1QBYyotVgRq2z2+ICbUdvSAWiS5NwwFmLJq227vPsNHIgZftuVzhUmBQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/universal": "3.1.48", + "ws": "8.21.0", + "xml2js": "0.6.2", + "yargs": "17.7.2" + }, + "bin": { + "xdebug-bridge": "xdebug-bridge.js" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@playwright/test": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.17.tgz", + "integrity": "sha512-tXDyE1/jzFsHXjhRZQ3hMl0IVhYe5qula43LDWIhVfjp9G/nT5OQY5AORVOrkEGAUltBJOfOWeETbmhm6kHhuQ==", + "license": "MIT", + "dependencies": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@prisma/instrumentation": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz", + "integrity": "sha512-mrZOev24EDhnefmnZX7WVVT7v+r9LttPRqf54ONvj6re4XMF7wFTpK2tLJi4XHB7fFp/6xhYbgRel8YV7gQiyA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.8" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", + "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@puppeteer/browsers/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==", + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "license": "MIT" + }, + "node_modules/@sentry/core": { + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.47.1.tgz", + "integrity": "sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node": { + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.47.1.tgz", + "integrity": "sha512-CDbkasBz3fnWRKSFs6mmaRepM2pa+tbZkrqhPWifFfIkJDidtVW40p6OnquTvPXyPAszCnDZRnZT14xyvNmKPQ==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.2", + "@opentelemetry/instrumentation-amqplib": "^0.46.1", + "@opentelemetry/instrumentation-connect": "0.43.1", + "@opentelemetry/instrumentation-dataloader": "0.16.1", + "@opentelemetry/instrumentation-express": "0.47.1", + "@opentelemetry/instrumentation-fs": "0.19.1", + "@opentelemetry/instrumentation-generic-pool": "0.43.1", + "@opentelemetry/instrumentation-graphql": "0.47.1", + "@opentelemetry/instrumentation-hapi": "0.45.2", + "@opentelemetry/instrumentation-http": "0.57.2", + "@opentelemetry/instrumentation-ioredis": "0.47.1", + "@opentelemetry/instrumentation-kafkajs": "0.7.1", + "@opentelemetry/instrumentation-knex": "0.44.1", + "@opentelemetry/instrumentation-koa": "0.47.1", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", + "@opentelemetry/instrumentation-mongodb": "0.52.0", + "@opentelemetry/instrumentation-mongoose": "0.46.1", + "@opentelemetry/instrumentation-mysql": "0.45.1", + "@opentelemetry/instrumentation-mysql2": "0.45.2", + "@opentelemetry/instrumentation-pg": "0.51.1", + "@opentelemetry/instrumentation-redis-4": "0.46.1", + "@opentelemetry/instrumentation-tedious": "0.18.1", + "@opentelemetry/instrumentation-undici": "0.10.1", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@prisma/instrumentation": "6.11.1", + "@sentry/core": "9.47.1", + "@sentry/node-core": "9.47.1", + "@sentry/opentelemetry": "9.47.1", + "import-in-the-middle": "^1.14.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node-core": { + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-9.47.1.tgz", + "integrity": "sha512-7TEOiCGkyShJ8CKtsri9lbgMCbB+qNts2Xq37itiMPN2m+lIukK3OX//L8DC5nfKYZlgikrefS63/vJtm669hQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.47.1", + "@sentry/opentelemetry": "9.47.1", + "import-in-the-middle": "^1.14.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/instrumentation": ">=0.57.1 <1", + "@opentelemetry/resources": "^1.30.1 || ^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, + "node_modules/@sentry/node/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@sentry/node/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.47.1.tgz", + "integrity": "sha512-STtFpjF7lwzeoedDJV+5XA6P89BfmFwFftmHSGSe3UTI8z8IoiR5yB6X2vCjSPvXlfeOs13qCNNCEZyznxM8Xw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.47.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@stylistic/stylelint-plugin": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.1.3.tgz", + "integrity": "sha512-85fsmzgsIVmyG3/GFrjuYj6Cz8rAM7IZiPiXCMiSMfoDOC1lOrzrXPDk24WqviAghnPqGpx8b0caK2PuewWGFg==", + "license": "MIT", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.1", + "@csstools/css-tokenizer": "^3.0.1", + "@csstools/media-query-list-parser": "^3.0.1", + "is-plain-object": "^5.0.0", + "postcss": "^8.4.41", + "postcss-selector-parser": "^6.1.2", + "postcss-value-parser": "^4.2.0", + "style-search": "^0.1.0" + }, + "engines": { + "node": "^18.12 || >=20.9" + }, + "peerDependencies": { + "stylelint": "^16.8.0" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@tannin/compile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz", + "integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==", + "license": "MIT", + "dependencies": { + "@tannin/evaluate": "^1.2.0", + "@tannin/postfix": "^1.1.0" + } + }, + "node_modules/@tannin/evaluate": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz", + "integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==", + "license": "MIT" + }, + "node_modules/@tannin/plural-forms": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz", + "integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==", + "license": "MIT", + "dependencies": { + "@tannin/compile": "^1.1.0" + } + }, + "node_modules/@tannin/postfix": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", + "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==", + "license": "MIT" + }, + "node_modules/@tannin/sprintf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@tannin/sprintf/-/sprintf-1.3.3.tgz", + "integrity": "sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==", + "license": "MIT" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.162", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.162.tgz", + "integrity": "sha512-Fn658grtLOci1oxi1391vvDWJRKNGWRSqfxRkmN/Iy3c0tQH1USMKEXcPYHLvope+ZgTFocx9FRQJx1muBL6qw==", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/btoa-lite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", + "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==", + "license": "MIT" + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.3.tgz", + "integrity": "sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jsdom": { + "version": "21.1.7", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", + "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "license": "MIT" + }, + "node_modules/@types/mousetrap": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz", + "integrity": "sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.66.0.tgz", + "integrity": "sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.66.0", + "@typescript-eslint/type-utils": "8.66.0", + "@typescript-eslint/utils": "8.66.0", + "@typescript-eslint/visitor-keys": "8.66.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.66.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.66.0.tgz", + "integrity": "sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.66.0", + "@typescript-eslint/types": "8.66.0", + "@typescript-eslint/typescript-estree": "8.66.0", + "@typescript-eslint/visitor-keys": "8.66.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/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==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.66.0.tgz", + "integrity": "sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.66.0", + "@typescript-eslint/types": "^8.66.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/project-service/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==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.66.0.tgz", + "integrity": "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.66.0", + "@typescript-eslint/visitor-keys": "8.66.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.66.0.tgz", + "integrity": "sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.66.0.tgz", + "integrity": "sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.66.0", + "@typescript-eslint/typescript-estree": "8.66.0", + "@typescript-eslint/utils": "8.66.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/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==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.66.0.tgz", + "integrity": "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.66.0.tgz", + "integrity": "sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.66.0", + "@typescript-eslint/tsconfig-utils": "8.66.0", + "@typescript-eslint/types": "8.66.0", + "@typescript-eslint/visitor-keys": "8.66.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.66.0.tgz", + "integrity": "sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.66.0", + "@typescript-eslint/types": "8.66.0", + "@typescript-eslint/typescript-estree": "8.66.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.66.0.tgz", + "integrity": "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.66.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@wordpress/babel-preset-default": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-8.52.0.tgz", + "integrity": "sha512-0beMLrvoMAHH3Q4916FEftMCkn0/lx+wg8JoxX80BjOTrCzZMQaArTgvmH2F0G9jvuhzqJebsNoqdrNvd6nTVQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/core": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-transform-react-jsx": "^7.25.7", + "@babel/plugin-transform-runtime": "^7.25.7", + "@babel/preset-env": "^7.25.7", + "@babel/preset-typescript": "^7.25.7", + "@wordpress/browserslist-config": "^6.52.0", + "@wordpress/warning": "^3.52.0", + "browserslist": "^4.28.4", + "core-js": "^3.31.0", + "react": "^18.3.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/base-styles": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-12.0.0.tgz", + "integrity": "sha512-BqSA9qZrBM9FBXFmQYvYCigA8ytkmlNFZ8+H0FscEnLWXkyCRwvHm4dE6LL53lmclKUGRMKlTZOUe1l8hfBQ5g==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/browserslist-config": { + "version": "6.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-6.52.0.tgz", + "integrity": "sha512-+4oOFS7wOuCc8ZRRT8rjoQbJCXX0li8tWN++1szH0qsRzSNVvZSu4gR7bIAK1GrQKhIjAUZItrT02iocBq7lIA==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/compose": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-8.5.0.tgz", + "integrity": "sha512-giYS22Tbhtr3Lj4lK6lxzGqV6EkM2QeVBiP7+c9r2F9rnQN3F6A8cN4gQM5sVGdgIOlps9tw+dsn9OHzIFVwIg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@types/mousetrap": "^1.6.8", + "@wordpress/deprecated": "^4.52.0", + "@wordpress/dom": "^4.52.0", + "@wordpress/element": "^8.4.0", + "@wordpress/is-shallow-equal": "^5.52.0", + "@wordpress/keycodes": "^4.52.0", + "@wordpress/priority-queue": "^3.52.0", + "@wordpress/private-apis": "^1.52.0", + "@wordpress/undo-manager": "^1.52.0", + "change-case": "^4.1.2", + "mousetrap": "^1.6.5", + "use-memo-one": "^1.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@types/react": "^18 || ^19", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@wordpress/dependency-extraction-webpack-plugin": { + "version": "6.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-6.52.0.tgz", + "integrity": "sha512-3cl4vODbsN2D+7E/y7QiOlm11lgWSsUBH8lnznFNuTPQc7LlqumyaY8Bxuek1BIBerbmam0R/Ww8krl1zSpvPQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "json2php": "^0.0.9" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@wordpress/deprecated": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.52.0.tgz", + "integrity": "sha512-94oHBKPty4pp6L5510LWDwJwNqFhikxLfwN6VUcDOQzj3itkc0MQ4ZQhmsfBy3Y6IRxSGx+p2bjSQvA4D+M96A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/hooks": "^4.52.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/dom": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-4.52.0.tgz", + "integrity": "sha512-LUY9nI9h6blk4xBuG83KgyfTnx7PMs/g6ZVzY/SOaCcOc2P3zOfzacADq/vxQydbZpcwtLM6juzgnNta6AX95w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/deprecated": "^4.52.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/e2e-test-utils-playwright": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-1.52.0.tgz", + "integrity": "sha512-LK0/WJd8iGfTo9ONaHrLSBh0IjKHeXU7urZPaNuXXB7jdt+coLTF+y0gP4c6sQ5m9OgfQqf01FPT/t2XzEbJ+w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "change-case": "^4.1.2", + "get-port": "^5.1.1", + "lighthouse": "^12.2.2", + "mime": "^3.0.0", + "web-vitals": "^4.2.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@playwright/test": ">=1", + "@types/node": "^20.17.10" + } + }, + "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@wordpress/element": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-8.4.0.tgz", + "integrity": "sha512-/LzW+0MpSmKfYiESoXUQtjBPqOPyvqUm17GigQR5c0Z8Wj2NiklP72x4XaF02uSkau1ru1Z9lP8NWEGjwBwLsA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@types/react": "^18.3.27", + "@types/react-dom": "^18.3.1", + "@wordpress/deprecated": "^4.52.0", + "@wordpress/escape-html": "^3.52.0", + "change-case": "^4.1.2", + "is-plain-object": "^5.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/escape-html": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-3.52.0.tgz", + "integrity": "sha512-sW8X839Xu8aiJlCGF48MM3iYrcXspuiY0By8iTpXKpnUdd2u0SL9HRR0ALSAsOf2ujOeWm/x58ODMSchovRWGw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/eslint-plugin": { + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/@wordpress/eslint-plugin/-/eslint-plugin-25.8.0.tgz", + "integrity": "sha512-QqYfiAVUYFLUhiLlVwB1MoGHcyNElwAPFeXnfZhYUPvFYOmQucsn4dxEGpl67PfcM2XWimni5z+mUquv4y1Mow==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/eslint-parser": "^7.28.6", + "@eslint-community/eslint-plugin-eslint-comments": "^4.7.0", + "@eslint/compat": "^2.0.0", + "@wordpress/babel-preset-default": "^8.52.0", + "@wordpress/prettier-config": "^4.52.0", + "@wordpress/theme": "^1.1.0", + "cosmiconfig": "^7.0.0", + "eslint-config-prettier": "^10.0.0", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest": "^29.16.0", + "eslint-plugin-jsdoc": "^50.0.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-playwright": "^2.1.0", + "eslint-plugin-prettier": "^5.5.5", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^16.0.0", + "requireindex": "^1.2.0", + "typescript-eslint": "^8.57.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@babel/core": ">=7", + "eslint": "^9.0.0 || ^10.0.0", + "prettier": ">=3", + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@wordpress/eslint-plugin/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@wordpress/hooks": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.52.0.tgz", + "integrity": "sha512-EbV/nJTerhqwNW3DLvvGutJfNyXcmBHXuWyJpv1NypzT80k21jPGP79HBE5Z0A2oAI2kIBp6Klaa4O8uEjq/sw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/i18n": { + "version": "6.24.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.24.0.tgz", + "integrity": "sha512-K4XmCyyyDOKH/5ea75P2L36ZiAvQTy4Hsa73Na3n6NzVjAwrrKZm4JJGf0t+OlThUG4D4GyfEv5szs5EeCA0lA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.51.0", + "gettext-parser": "^1.3.1", + "memize": "^2.1.0", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/is-shallow-equal": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-5.52.0.tgz", + "integrity": "sha512-LMIBLLTZ+vvq0DlYebL4d9XaCu16PNnhPGSn8QqsMPmBzwBYOjO0/btMLpYbs9rRc8k1QKBDWvw8eddvRVsYxA==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/jest-console": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-8.51.0.tgz", + "integrity": "sha512-NhX7hJy0XFYnsjca7RuV7jHsHotRAwKFi8md5By+EJaBdO3itAcBv5/QLLyGBgNXGSvEVGVQfzym/S8CeC8b0Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "jest-matcher-utils": "^29.6.2", + "jest-mock": "^29.6.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "jest": ">=29" + } + }, + "node_modules/@wordpress/jest-preset-default": { + "version": "12.51.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-preset-default/-/jest-preset-default-12.51.0.tgz", + "integrity": "sha512-fJFOCdQHnutv+esdusNufxkrKsCW63UFrgFXWLwGr66YR9q0Z+d1Mw6BVFf7kvzGjT166PBJumf2XTRqUedPNQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/jest-console": "^8.51.0", + "babel-jest": "^29.7.0", + "change-case": "^4.1.2" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@babel/core": ">=7", + "jest": ">=29" + } + }, + "node_modules/@wordpress/keycodes": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-4.52.0.tgz", + "integrity": "sha512-KRvwViTTdxUDgikYaCm+qnXSH2UlFuCDjAIvtjjcen8oRviSkeMv6bPn1T2vqFRKcVgt88xTtKlvI8l5U99o2Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/i18n": "^6.25.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@types/react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@wordpress/keycodes/node_modules/@wordpress/i18n": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.25.0.tgz", + "integrity": "sha512-UcyUT8CJgEkhjzEGTVV6kw0Qi4OraF0I9J9FBLmTda/1Wi1o6rLAXZBm2aJrP740ezFxPneHH92aQF4Z5xZqcQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.52.0", + "gettext-parser": "^1.3.1", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/npm-package-json-lint-config": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-5.52.0.tgz", + "integrity": "sha512-+3fv1jmdmsvSIhlZ2PpYKVQ6VQ1zKJFMTbHoJKSSiUA0Os5ASgAAH6S/+s4B0EGHZ94G3SV3k8oaiOnwOghE5Q==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "npm-package-json-lint": ">=6.0.0" + } + }, + "node_modules/@wordpress/postcss-plugins-preset": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-5.52.0.tgz", + "integrity": "sha512-/Wvo88zPqzHlLJR51JAuLm1jrMEt+tAnvmTs2xhysigFuH9gv4UN8sNf8kGmMwPMneSl2MAlLAd5ilkBTcRVag==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/base-styles": "^12.0.0", + "@wordpress/browserslist-config": "^6.52.0", + "autoprefixer": "^10.4.21", + "postcss-import": "^16.1.1" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/@wordpress/prettier-config": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/prettier-config/-/prettier-config-4.52.0.tgz", + "integrity": "sha512-aUxF/a7BtcfIVaJn12eZOwMUPJFMCu37wEyR+KhzR5gXssXi5yGqxJKNIHT/dmTyYC+MNxVM73g+W1HyAoIwxw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "prettier": ">=3" + } + }, + "node_modules/@wordpress/priority-queue": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-3.52.0.tgz", + "integrity": "sha512-aYnVXxV5j4D73tRld2n1D3G6cKLfSwKWcTnktJ7XlmiswW7xlaAqvn4FyBjwmIe20pZw0A7xLH5xCuQcqOM7nw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "requestidlecallback": "^0.3.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/private-apis": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/private-apis/-/private-apis-1.52.0.tgz", + "integrity": "sha512-gFcmBXSti73Y4uEx++5qUNDaH/o0/2ijrHEJkY5e/df4RtmxVSQOIVxftRiI4m9thCWfJMoehMMreJxhwx6Qtg==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/scripts": { + "version": "32.6.0", + "resolved": "https://registry.npmjs.org/@wordpress/scripts/-/scripts-32.6.0.tgz", + "integrity": "sha512-nO5s2RYmOWiVjcG3/zp5NEejLu+J/dzujRIl633hd9yj8gBtQRKfZr/iAwyFQwW0Asn15bbwc1I0b4+lvnumOw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/core": "^7.25.7", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", + "@svgr/webpack": "^8.0.1", + "@wordpress/babel-preset-default": "^8.50.0", + "@wordpress/browserslist-config": "^6.50.0", + "@wordpress/dependency-extraction-webpack-plugin": "^6.50.0", + "@wordpress/e2e-test-utils-playwright": "^1.50.0", + "@wordpress/eslint-plugin": "^25.6.0", + "@wordpress/jest-preset-default": "^12.50.0", + "@wordpress/npm-package-json-lint-config": "^5.50.0", + "@wordpress/postcss-plugins-preset": "^5.50.0", + "@wordpress/prettier-config": "^4.50.0", + "@wordpress/stylelint-config": "^23.42.0", + "adm-zip": "^0.5.9", + "babel-jest": "^29.7.0", + "babel-loader": "^9.2.1", + "browserslist": "^4.21.10", + "chalk": "^4.1.1", + "check-node-version": "^4.1.0", + "copy-webpack-plugin": "^10.2.0", + "cross-spawn": "^7.0.6", + "css-loader": "^6.2.0", + "cssnano": "^6.0.1", + "cwd": "^0.10.0", + "dir-glob": "^3.0.1", + "eslint": "^10.0.0", + "expect-puppeteer": "^4.4.0", + "fast-glob": "^3.2.7", + "filenamify": "^4.2.0", + "jest": "^29.6.2", + "jest-dev-server": "^10.1.4", + "jest-environment-jsdom": "^30.2.0", + "jest-environment-node": "^29.6.2", + "json2php": "^0.0.9", + "markdownlint-cli": "^0.31.1", + "merge-deep": "^3.0.3", + "mini-css-extract-plugin": "^2.9.2", + "minimist": "^1.2.0", + "npm-package-json-lint": "^6.4.0", + "npm-packlist": "^3.0.0", + "postcss": "^8.4.38", + "postcss-loader": "^6.2.1", + "prettier": "npm:wp-prettier@^3.0.3", + "puppeteer-core": "^23.10.1", + "react-refresh": "^0.14.0", + "read-pkg-up": "^7.0.1", + "resolve-bin": "^0.4.0", + "rtlcss": "^4.3.0", + "sass": "^1.54.0", + "sass-loader": "^16.0.3", + "schema-utils": "^4.2.0", + "source-map-loader": "^3.0.0", + "stylelint": "^16.8.2", + "terser-webpack-plugin": "^5.3.10", + "url-loader": "^4.1.1", + "webpack": "^5.97.0", + "webpack-bundle-analyzer": "^4.9.1", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.15.1" + }, + "bin": { + "wp-scripts": "bin/wp-scripts.js" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@playwright/test": "^1.58.2", + "@wordpress/env": ">=10.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@wordpress/env": { + "optional": true + } + } + }, + "node_modules/@wordpress/scripts/node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@wordpress/scripts/node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@wordpress/scripts/node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@wordpress/scripts/node_modules/@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@wordpress/scripts/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@wordpress/scripts/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@wordpress/scripts/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@wordpress/scripts/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@wordpress/scripts/node_modules/eslint": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", + "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/@wordpress/scripts/node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@wordpress/scripts/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@wordpress/scripts/node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@wordpress/scripts/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wordpress/scripts/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/@wordpress/scripts/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wordpress/scripts/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wordpress/scripts/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==", + "license": "MIT" + }, + "node_modules/@wordpress/scripts/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wordpress/style-runtime": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wordpress/style-runtime/-/style-runtime-0.8.0.tgz", + "integrity": "sha512-gqe5cnsDLwH2NQ//VyUtzS4pcht0iR64hP+3u6p5/pPvwA2ySGn71mJ/7+O2X7sUG5drxNp6+4Kl3LWOzkKYng==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wordpress/stylelint-config": { + "version": "23.42.0", + "resolved": "https://registry.npmjs.org/@wordpress/stylelint-config/-/stylelint-config-23.42.0.tgz", + "integrity": "sha512-k9lNU4sK3fdipdhHI2d/Rzd/NnfznPmOZ60ok8O8QhfCMZw2Jd1M8ckYqaIrHTKU62ZrcsugdfJlHodsdrxEzA==", + "license": "MIT", + "dependencies": { + "@stylistic/stylelint-plugin": "^3.0.1", + "@wordpress/theme": "^0.17.0", + "stylelint-config-recommended": "^14.0.1", + "stylelint-config-recommended-scss": "^14.1.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "stylelint": "^16.8.2", + "stylelint-scss": "^6.4.0" + } + }, + "node_modules/@wordpress/stylelint-config/node_modules/@wordpress/style-runtime": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@wordpress/style-runtime/-/style-runtime-0.5.0.tgz", + "integrity": "sha512-hrXvdDUJpOzT1KIomgtysysgbc5bkkwAuJyEUAXiOCgVBXBeMkZlgfN19W0PuNY51j53K7VQ42txfayxgVmfgA==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wordpress/stylelint-config/node_modules/@wordpress/theme": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@wordpress/theme/-/theme-0.17.0.tgz", + "integrity": "sha512-BU+PLBLxMBM4WJYrd1QEwy+IA64vUP+8IEEB9lLx2NfB+3/45vvuvXx9o3qPKRDHvtMtEaRArld4Kn05UIW9IA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/compose": "^8.2.0", + "@wordpress/deprecated": "^4.49.0", + "@wordpress/element": "^8.1.0", + "@wordpress/private-apis": "^1.49.0", + "@wordpress/style-runtime": "^0.5.0", + "colorjs.io": "^0.6.0", + "memize": "^2.1.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "@types/react": "^18.3.27", + "esbuild": "^0.27.2", + "postcss": "^8.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", + "stylelint": "^16.8.2", + "vite": "^7.3.2" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "postcss": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@wordpress/stylelint-config/node_modules/colorjs.io": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.6.1.tgz", + "integrity": "sha512-8lyR2wHzuIykCpqHKgluGsqQi5iDm3/a2IgP2GBZrasn2sBRkE4NOGsglZxWLs/jZQoNkmA/KM/8NV16rLUdBg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/color" + } + }, + "node_modules/@wordpress/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-SWEGYY/HnSzmKDJnDhWVfxUDyLlJkz9EtpfAWhgPcCLSaZVc/pp99Fxr+/ueB2mHlQ9gpaWCPAMBxq8knDCbXw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/compose": "^8.5.0", + "@wordpress/deprecated": "^4.52.0", + "@wordpress/element": "^8.4.0", + "@wordpress/private-apis": "^1.52.0", + "@wordpress/style-runtime": "^0.8.0", + "colorjs.io": "^0.7.1", + "memize": "^2.1.1" + }, + "engines": { + "node": "^20.19.0 || >=22.13.0", + "npm": ">=10.2.3" + }, + "peerDependencies": { + "@types/react": "^18 || ^19", + "esbuild": ">=0.27.2 <1.0.0", + "postcss": "^8.0.0", + "react": "^18 || ^19", + "react-dom": "^18 || ^19", + "stylelint": "^16 || ^17", + "vite": "^7 || ^8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "postcss": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@wordpress/undo-manager": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/undo-manager/-/undo-manager-1.52.0.tgz", + "integrity": "sha512-6hI0WWDOtLLVEkWqQokCoQRz5Pba9UNtgt5MV4hHGe5x0mzsowj+GWHedppf8UCVZ2ex3cde7fThaRKMCackrQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/is-shallow-equal": "^5.52.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/warning": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-3.52.0.tgz", + "integrity": "sha512-BjJ+Jte1g2nMITI1IHq0NwMpm/qlFOV1L+gNe0vFQmGKEcXiQ0DjrHQNtA8hV+Mgt9zSWRNS71Fgonht3r72Ew==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wp-playground/blueprints": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-3.1.48.tgz", + "integrity": "sha512-geJ1EdIWpRFxgnJrJqsYq+YUEJAFenKI6OCRRAfvgRAN+pei7HpCpSEnMcYB2atmpj6DtpqpKGlg3Yf1/EoRBA==", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@php-wasm/web-service-worker": "3.1.48", + "@wp-playground/common": "3.1.48", + "@wp-playground/storage": "3.1.48", + "@wp-playground/wordpress": "3.1.48", + "ajv": "8.18.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/cli": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/cli/-/cli-3.1.48.tgz", + "integrity": "sha512-24Y640IHzv7t/iEep1cUU5kZwUFTDXqljTRqOtddzQNByZzxL4g0zXSQYVUq6IPCh9rVx3/+elId/Ym6MCzRZA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/cli-util": "3.1.48", + "@php-wasm/logger": "3.1.48", + "@php-wasm/node": "3.1.48", + "@php-wasm/progress": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@php-wasm/xdebug-bridge": "3.1.48", + "@wp-playground/blueprints": "3.1.48", + "@wp-playground/common": "3.1.48", + "@wp-playground/storage": "3.1.48", + "@wp-playground/tools": "3.1.48", + "@wp-playground/wordpress": "3.1.48", + "express": "4.22.2", + "fs-extra": "11.1.1", + "tmp-promise": "3.0.3", + "wasm-feature-detect": "1.8.0", + "yargs": "17.7.2" + }, + "bin": { + "wp-playground-cli": "wp-playground.js" + } + }, + "node_modules/@wp-playground/common": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-3.1.48.tgz", + "integrity": "sha512-+k7Ku33GWROchZmE0mP23aPTdCXxR7uZqsSgfpf+ttjuKB8uOI9TzfcqrRfSoLcqN2Rh7FAvJmtgbcgdOLfl+A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/storage": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-3.1.48.tgz", + "integrity": "sha512-5WMK4PpL5ETkoMsKPgLCwQ5b8Uz5PgFu0uvG+2tgSu7v8x2/GjuLsLloUl2vrPEu3ZrVDXrMOYnBiX8oEHcAPg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/stream-compression": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@zip.js/zip.js": "2.7.57", + "isomorphic-git": "1.37.6", + "octokit": "3.1.2", + "pako": "^1.0.10", + "sha.js": "2.4.12" + } + }, + "node_modules/@wp-playground/tools": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/tools/-/tools-3.1.48.tgz", + "integrity": "sha512-HnsBfBkMt7YrhO1d867uQg1OivEoPOKlAuEYwXkabv644O95hO5MrQQWv888qQIPHeKJKzXYjmGEL8KwCy9bGw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/util": "3.1.48", + "@wp-playground/blueprints": "3.1.48" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@wp-playground/wordpress": { + "version": "3.1.48", + "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-3.1.48.tgz", + "integrity": "sha512-L0TSLNAoCXnHo9Ar4/0oTzM2OmJfhmQbko+ypf7EJhXILN73IsOhbAXp2MWfSUt24+rGGb6Z9BzlXmGPD6Brsw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/logger": "3.1.48", + "@php-wasm/universal": "3.1.48", + "@php-wasm/util": "3.1.48", + "@wp-playground/common": "3.1.48", + "zstddec": "^0.2.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/@zip.js/zip.js": { + "version": "2.7.57", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.57.tgz", + "integrity": "sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA==", + "license": "BSD-3-Clause", + "engines": { + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=16.5.0" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "license": "BSD-3-Clause" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.18.tgz", + "integrity": "sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "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-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "license": "MIT", + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atomically": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-2.1.1.tgz", + "integrity": "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ==", + "license": "MIT", + "dependencies": { + "stubborn-fs": "^2.0.0", + "when-exit": "^2.1.4" + } + }, + "node_modules/autoprefixer": { + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", + "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.6", + "caniuse-lite": "^1.0.30001806", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/axios/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/axios/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/axios/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==", + "license": "MIT" + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.1.tgz", + "integrity": "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.8.0.tgz", + "integrity": "sha512-fM+MhCvdQhZ7NV6S95a07gPSqjIYKn6mFaXfx266wN3ajZGl/+1AzH+ubkXQ0fFZvOe2nk9VHkzdYkQE5zMV3Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.28.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.1.1.tgz", + "integrity": "sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==", + "license": "Apache-2.0" + }, + "node_modules/bare-stream": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.3.tgz", + "integrity": "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.8.1", + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-stream/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.5.1.tgz", + "integrity": "sha512-cD5ciQuKlx+eumTCfqbfiL+fhQm+dHbVNB/cX4+d+I/nx4JsVop9VoFEPAs5RJ6I84QR6bZIBjpd2kjDOYeWcg==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", + "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "license": "Apache-2.0" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "license": "MIT", + "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.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bonjour-service": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.4.4.tgz", + "integrity": "sha512-jCZcVv7eoc4QesRscwEZtSROBen+6LpKAmBIsQYQrsAeVHLyMXWX/t6eIV5KiRZYNUBl8eVqImEEMQ8L5+c/Kw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", + "license": "MIT" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", + "license": "MIT", + "dependencies": { + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" + } + }, + "node_modules/cacheable/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/check-node-version": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/check-node-version/-/check-node-version-4.2.1.tgz", + "integrity": "sha512-YYmFYHV/X7kSJhuN/QYHUu998n/TRuDe8UenM3+m5NrkiH670lb9ILqHIvBencvJc4SDh+XcbXMR4b+TtubJiw==", + "license": "Unlicense", + "dependencies": { + "chalk": "^3.0.0", + "map-values": "^1.0.1", + "minimist": "^1.2.0", + "object-filter": "^1.0.2", + "run-parallel": "^1.1.4", + "semver": "^6.3.0" + }, + "bin": { + "check-node-version": "bin.js" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/check-node-version/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-node-version/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chrome-launcher": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.2.1.tgz", + "integrity": "sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^2.0.1" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.cjs" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chromium-bidi": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", + "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/chromium-bidi/node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "license": "Apache-2.0" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", + "license": "MIT", + "dependencies": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/colorjs.io": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.7.1.tgz", + "integrity": "sha512-LY7OHnJZxHwT5UlzNa9bbhHHDbzB6yE5+3MIPwJEQKRvSCt/T4G7epsj+9j2BExUIIfXFIJGsIXUKdfrK9Q5tA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/color" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/configstore": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-7.1.0.tgz", + "integrity": "sha512-N4oog6YJWbR9kGyXvS7jEykLDXIE2C0ILYqNBZBp9iwiJpoCBWYsuAdW6PPFn6w06jjnC+3JstVvWHO4cZqvRg==", + "license": "BSD-2-Clause", + "dependencies": { + "atomically": "^2.0.3", + "dot-prop": "^9.0.0", + "graceful-fs": "^4.2.11", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 12.20.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/core-js": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.7" + }, + "engines": { + "node": ">=6.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.50.0.tgz", + "integrity": "sha512-6GP3Pxz4IKyWjAfa747vIu/jilB5z29JWROLqH/b+pXVcpgh6tM06ZIBwSuglgVqzDYURhOK6oEzTrG0bCHitA==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csp_evaluator": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.5.tgz", + "integrity": "sha512-EL/iN9etCTzw/fBnp0/uj0f5BOOGvZut2mzsiiBZ/FdT6gFQCKRO/tmcKOxn5drWZ2Ndm/xBb1SI4zwWbGtmIw==", + "license": "Apache-2.0" + }, + "node_modules/css-declaration-sorter": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-functions-list": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/cwd": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", + "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", + "license": "MIT", + "dependencies": { + "find-pkg": "^0.1.2", + "fs-exists-sync": "^0.1.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "license": "BSD-2-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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==", + "license": "MIT", + "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/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/devtools-protocol": { + "version": "0.0.1507524", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1507524.tgz", + "integrity": "sha512-OjaNE7qpk6GRTXtqQjAE5bGx6+c4F1zZH0YXtpZQLM92HNXx4zMAaqlKhP4T52DosG6hDW8gPMNhGOF8xbwk/w==", + "license": "BSD-3-Clause" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.403", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.403.tgz", + "integrity": "sha512-MQsYmdaLzvaCX5j+ZZBr5Fm6uCCnPQcRtlvmvRlWqrXy+BH2O4ffXIAScF+JQznQWB9brWp4lSD9Z4yNmaf2BA==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/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==", + "license": "MIT" + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.5.tgz", + "integrity": "sha512-nbE5XLph6TLtGYcu/U6e6ZVXyKBhbDWK5cLGk76eJ7NdZpwf1P9EFkpt1Z01mNZNrrilsAYWKH6zUkL4reoXbw==", + "license": "ISC", + "dependencies": { + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^16.17.0 || >=18.6.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/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==", + "license": "MIT" + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/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==", + "license": "MIT" + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/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==", + "license": "MIT" + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "29.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.16.0.tgz", + "integrity": "sha512-0WFBxDHlT2ratGQfnFQEVIsgQJ5cfd+0IV8Kc6U3X2onB8ATLG23voD2Ch5G9fCkEpCPmCMuzW0tbS0kYb8biw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "jest": "*", + "typescript": ">=4.8.4 <8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "50.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.8.0.tgz", + "integrity": "sha512-UyGb5755LMFWPrZTEqqvTJ3urLz1iqj+bYOHFNag+sw3NvaMWP9K2z+uIn37XfNALmQLQyrBlJ5mkiVPL7ADEg==", + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.50.2", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.4.1", + "escape-string-regexp": "^4.0.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc/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==", + "license": "MIT" + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/eslint-plugin-playwright": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.11.0.tgz", + "integrity": "sha512-zOIEYyv1TSn2izXkyg/yj0LXc4YBQI6pl3xIFWwMCcXt/dgQCz8dBqXiXFMoM3xc/GqZThAtaGYo8aPu/vBd+Q==", + "license": "MIT", + "dependencies": { + "globals": "^17.3.0" + }, + "engines": { + "node": ">=16.9.0" + }, + "peerDependencies": { + "eslint": ">=8.40.0" + } + }, + "node_modules/eslint-plugin-playwright/node_modules/globals": { + "version": "17.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.9.0.tgz", + "integrity": "sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT", + "peer": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "license": "MIT", + "peer": true + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", + "license": "MIT", + "dependencies": { + "os-homedir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/expect-puppeteer": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", + "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", + "license": "MIT" + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "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.15.1", + "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/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip/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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-builder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.0.tgz", + "integrity": "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.10.1.tgz", + "integrity": "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^3.0.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.1", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "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.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-file-up": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", + "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", + "license": "MIT", + "dependencies": { + "fs-exists-sync": "^0.1.0", + "resolve-dir": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-parent-dir": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.1.tgz", + "integrity": "sha512-o4UcykWV/XN9wm+jMEtWLPlV8RXCZnMhQI6F6OdHeSez7iiJWePw8ijOlskJZMsaQoGR/b7dH6lO02HhaTN7+A==", + "license": "MIT" + }, + "node_modules/find-pkg": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", + "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", + "license": "MIT", + "dependencies": { + "find-file-up": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-process": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.11.tgz", + "integrity": "sha512-mAOh9gGk9WZ4ip5UjV0o6Vb4SrfnAmtsFNzkMRH9HQiFXVQnDyQFrSHTK5UoG6E+KV+s+cIznbtwpfN41l2nFA==", + "license": "MIT", + "dependencies": { + "chalk": "~4.1.2", + "commander": "^12.1.0", + "loglevel": "^1.9.2" + }, + "bin": { + "find-process": "bin/find-process.js" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "license": "MIT", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-ext-extra-prebuilt": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fs-ext-extra-prebuilt/-/fs-ext-extra-prebuilt-2.2.7.tgz", + "integrity": "sha512-Q7rayYRBDIvDF01HWOwSSjoaP+05N1g+o3BXL1Zf8Frw2JkjSmi4EtvCBITuW30l6hB2m2TW1pehdh8wyU/+gw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "nan": "^2.24.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", + "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", + "license": "Unlicense" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "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==", + "license": "MIT", + "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-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.1.tgz", + "integrity": "sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/get-uri/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==", + "license": "MIT" + }, + "node_modules/gettext-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", + "integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==", + "license": "MIT", + "dependencies": { + "encoding": "^0.1.12", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", + "license": "MIT", + "dependencies": { + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "license": "MIT", + "dependencies": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "license": "MIT", + "dependencies": { + "hookified": "^1.15.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "license": "MIT", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-link-header": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.4.tgz", + "integrity": "sha512-xT3GPW6/ZbGuw4UvwHqErSCEjNUlwbQJuZn9/q5U4WEKfp2kENVCAlousG1zLxHeaQ/ffOHUNpWamvkbBW0eNw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/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==", + "license": "MIT" + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.10.tgz", + "integrity": "sha512-RKzRWNPxUZqbuk3BC5mGVJbBnWgr+diEnjJexIOytFbBzDy88Fbh/YvBr3DsNrl1jYAfjWfpATEv0NO35FDuPQ==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/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==", + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "license": "ISC", + "dependencies": { + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/image-ssim": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", + "license": "MIT" + }, + "node_modules/immutable": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/intl-messageformat": { + "version": "10.7.18", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", + "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/icu-messageformat-parser": "2.11.4", + "tslib": "^2.8.0" + } + }, + "node_modules/ip-address": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/irregular-plurals": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "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-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "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-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "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-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "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==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unsafe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.0.tgz", + "integrity": "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-git": { + "version": "1.37.6", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.37.6.tgz", + "integrity": "sha512-qr1NFCPsVTZ6YGqTXw0CzamnsHyH9QQ1OTEfeXIweSljRUMzuHFCJdUn0wc6OcjtTDns6knxjPb7N6LmJeftOA==", + "license": "MIT", + "dependencies": { + "async-lock": "^1.4.1", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^4.0.0", + "sha.js": "^2.4.12", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/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==", + "license": "MIT" + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-dev-server": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-10.1.4.tgz", + "integrity": "sha512-bGQ6sedNGtT6AFHhCVqGTXMPz7UyJi/ZrhNBgyqsP0XU9N8acCEIfqZEA22rOaZ+NdEVsaltk6tL7UT6aXfI7w==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "cwd": "^0.10.0", + "find-process": "^1.4.7", + "prompts": "^2.4.2", + "spawnd": "^10.1.4", + "tree-kill": "^1.2.2", + "wait-on": "^8.0.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.4.1.tgz", + "integrity": "sha512-o3nfaN4zej7qgk2X0j8Jhq/S9nAVKs2xK3QeQxeHVvpkEPxaA1yxDGydR+iVI7zPy7Cp62Aq2h3Ja46QvfWHGA==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/environment-jsdom-abstract": "30.4.1", + "jsdom": "^26.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/environment": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", + "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-mock": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/fake-timers": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", + "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@sinonjs/fake-timers": "^15.4.0", + "@types/node": "*", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/schemas": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/types": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", + "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.4.0", + "@jest/schemas": "30.4.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@sinclair/typebox": { + "version": "0.34.52", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", + "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", + "license": "MIT" + }, + "node_modules/jest-environment-jsdom/node_modules/@sinonjs/fake-timers": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", + "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/jest-environment-jsdom/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-environment-jsdom/node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-message-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", + "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.4.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-util": "30.4.1", + "picomatch": "^4.0.3", + "pretty-format": "30.4.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-mock": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", + "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", + "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-environment-jsdom/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joi": { + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-18.2.3.tgz", + "integrity": "sha512-N5A3KTWQpPWT4ExxxPlUx7WmykGXRzhNidWhV41d6Abu9YfI2NyWCJuxdPnslJCPWtbRpSVOWSnSS6GakLM/Rg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "^5.1.1", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.7", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.1.1", + "@hapi/topo": "^6.0.2", + "@standard-schema/spec": "^1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "license": "BSD-3-Clause" + }, + "node_modules/js-library-detector": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", + "integrity": "sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", + "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" + }, + "node_modules/json2php": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/json2php/-/json2php-0.0.9.tgz", + "integrity": "sha512-fQMYwvPsQt8hxRnCGyg1r2JVi6yL8Um0DIIawiKiMK9yhAAkcRNj5UsBWoaFvFzPpcWbgw9L6wzj+UMYA702Mw==", + "license": "BSD" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/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==", + "license": "MIT" + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/known-css-properties": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", + "license": "MIT" + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz", + "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.4" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/legacy-javascript": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/legacy-javascript/-/legacy-javascript-0.0.1.tgz", + "integrity": "sha512-lPyntS4/aS7jpuvOlitZDFifBCb4W8L/3QU0PLbUTUj+zYah8rfVjYic88yG7ZKTxhS5h9iz7duT8oUXKszLhg==", + "license": "Apache-2.0" + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lighthouse": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-12.8.2.tgz", + "integrity": "sha512-+5SKYzVaTFj22MgoYDPNrP9tlD2/Ay7j3SxPSFD9FpPyVxGr4UtOQGKyrdZ7wCmcnBaFk0mCkPfARU3CsE0nvA==", + "license": "Apache-2.0", + "dependencies": { + "@paulirish/trace_engine": "0.0.59", + "@sentry/node": "^9.28.1", + "axe-core": "^4.10.3", + "chrome-launcher": "^1.2.0", + "configstore": "^7.0.0", + "csp_evaluator": "1.1.5", + "devtools-protocol": "0.0.1507524", + "enquirer": "^2.3.6", + "http-link-header": "^1.1.1", + "intl-messageformat": "^10.5.3", + "jpeg-js": "^0.4.4", + "js-library-detector": "^6.7.0", + "lighthouse-logger": "^2.0.2", + "lighthouse-stack-packs": "1.12.2", + "lodash-es": "^4.17.21", + "lookup-closest-locale": "6.2.0", + "metaviewport-parser": "0.3.0", + "open": "^8.4.0", + "parse-cache-control": "1.0.1", + "puppeteer-core": "^24.17.1", + "robots-parser": "^3.0.1", + "speedline-core": "^1.4.3", + "third-party-web": "^0.27.0", + "tldts-icann": "^7.0.12", + "ws": "^7.0.0", + "yargs": "^17.3.1", + "yargs-parser": "^21.0.0" + }, + "bin": { + "chrome-debug": "core/scripts/manual-chrome-launcher.js", + "lighthouse": "cli/index.js", + "smokehouse": "cli/test/smokehouse/frontends/smokehouse-bin.js" + }, + "engines": { + "node": ">=18.16" + } + }, + "node_modules/lighthouse-logger": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-2.0.2.tgz", + "integrity": "sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.1", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lighthouse-logger/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==", + "license": "MIT" + }, + "node_modules/lighthouse-stack-packs": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.12.2.tgz", + "integrity": "sha512-Ug8feS/A+92TMTCK6yHYLwaFMuelK/hAKRMdldYkMNwv+d9PtWxjXEg6rwKtsUXTADajhdrhXyuNCJ5/sfmPFw==", + "license": "Apache-2.0" + }, + "node_modules/lighthouse/node_modules/@puppeteer/browsers": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.2.tgz", + "integrity": "sha512-5EUZSUIc37H6aIXyWO0Z4y8NlF8NnjgmqeQgOGiswAU7pY0HOo16ho4+alIWmSfdZnjqBRawMsP3I5YqLSn6kw==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.3", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.4", + "tar-fs": "^3.1.1", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/lighthouse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lighthouse/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==", + "license": "MIT" + }, + "node_modules/lighthouse/node_modules/puppeteer-core": { + "version": "24.43.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.43.1.tgz", + "integrity": "sha512-T5ScUMAsmhdNbgDR41AGESYeS6V9MSgetkSnVhhW+gXvzC42VesKCn5ld87gAZDJ6vLHL9GkRvY9WtQWSnwFbw==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.13.2", + "chromium-bidi": "14.0.0", + "debug": "^4.4.3", + "devtools-protocol": "0.0.1608973", + "typed-query-selector": "^2.12.2", + "webdriver-bidi-protocol": "0.4.1", + "ws": "^8.20.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/chromium-bidi": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz", + "integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/devtools-protocol": { + "version": "0.0.1608973", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz", + "integrity": "sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ==", + "license": "BSD-3-Clause" + }, + "node_modules/lighthouse/node_modules/puppeteer-core/node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/lighthouse/node_modules/ws": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", + "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/lighthouse/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/lookup-closest-locale": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "name": "@wolfy1339/lru-cache", + "version": "11.0.2-patch.1", + "resolved": "https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz", + "integrity": "sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==", + "license": "ISC", + "engines": { + "node": "18 >=18.20 || 20 || >=22" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/map-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", + "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", + "license": "Public Domain" + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/markdownlint": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", + "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", + "license": "MIT", + "dependencies": { + "markdown-it": "12.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/markdownlint-cli": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.31.1.tgz", + "integrity": "sha512-keIOMwQn+Ch7MoBwA+TdkyVMuxAeZFEGmIIlvwgV0Z1TGS5MxPnRr29XCLhkNzCHU+uNKGjU+VEjLX+Z9kli6g==", + "license": "MIT", + "dependencies": { + "commander": "~9.0.0", + "get-stdin": "~9.0.0", + "glob": "~7.2.0", + "ignore": "~5.2.0", + "js-yaml": "^4.1.0", + "jsonc-parser": "~3.0.0", + "markdownlint": "~0.25.1", + "markdownlint-rule-helpers": "~0.16.0", + "minimatch": "~3.0.5", + "run-con": "~1.2.10" + }, + "bin": { + "markdownlint": "markdownlint.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/markdownlint-cli/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/markdownlint-cli/node_modules/commander": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", + "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/markdownlint-cli/node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/markdownlint-cli/node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/markdownlint-cli/node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "license": "MIT" + }, + "node_modules/markdownlint-cli/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/markdownlint-rule-helpers": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz", + "integrity": "sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==", + "license": "MIT" + }, + "node_modules/marky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", + "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", + "license": "Apache-2.0" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memize": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/memize/-/memize-2.1.1.tgz", + "integrity": "sha512-8Nl+i9S5D6KXnruM03Jgjb+LwSupvR13WBr4hJegaaEyobvowCVupi79y2WSiWvO1mzBWxPwEYE5feCe8vyA5w==", + "license": "MIT" + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-deep": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", + "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", + "license": "MIT", + "dependencies": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/metaviewport-parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.3.0.tgz", + "integrity": "sha512-EoYJ8xfjQ6kpe9VbVHvZTZHiOl4HL1Z18CrZ+qahvLXT7ZO4YTC2JMyt5FaUp9JJp6J4Ybb/z7IsCXZt86/QkQ==", + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minimist-options/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + } + }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/minimizer-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/minimizer-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", + "license": "MIT", + "dependencies": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-object/node_modules/for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/mousetrap": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==", + "license": "Apache-2.0 WITH LLVM-exception" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nan": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", + "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-forge": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "license": "ISC" + }, + "node_modules/npm-package-json-lint": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-6.4.0.tgz", + "integrity": "sha512-cuXAJJB1Rdqz0UO6w524matlBqDBjcNt7Ru+RDIu4y6RI1gVqiWBnylrK8sPRk81gGBA0X8hJbDXolVOoTc+sA==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "ajv-errors": "^1.0.1", + "chalk": "^4.1.2", + "cosmiconfig": "^8.0.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "ignore": "^5.2.0", + "is-plain-obj": "^3.0.0", + "jsonc-parser": "^3.2.0", + "log-symbols": "^4.1.0", + "meow": "^9.0.0", + "plur": "^4.0.0", + "semver": "^7.3.8", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1", + "type-fest": "^3.2.0", + "validate-npm-package-name": "^5.0.0" + }, + "bin": { + "npmPkgJsonLint": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/npm-package-json-lint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/npm-package-json-lint/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-package-json-lint/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm-package-json-lint/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-package-json-lint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/npm-package-json-lint/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==", + "license": "MIT" + }, + "node_modules/npm-package-json-lint/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-packlist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", + "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "license": "ISC", + "dependencies": { + "glob": "^7.1.6", + "ignore-walk": "^4.0.1", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-filter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", + "integrity": "sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "license": "MIT" + }, + "node_modules/octokit": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/octokit/-/octokit-3.1.2.tgz", + "integrity": "sha512-MG5qmrTL5y8KYwFgE1A4JWmgfQBaIETE/lOlfwNYx1QOtCQHGVxkRJmdUJltFc1HVn73d61TlMhMyNTOtMl+ng==", + "license": "MIT", + "dependencies": { + "@octokit/app": "^14.0.2", + "@octokit/core": "^5.0.0", + "@octokit/oauth-app": "^6.0.0", + "@octokit/plugin-paginate-graphql": "^4.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0", + "@octokit/plugin-retry": "^6.0.0", + "@octokit/plugin-throttling": "^8.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pac-proxy-agent/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==", + "license": "MIT" + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" + }, + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "license": "MIT" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.16.0.tgz", + "integrity": "sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/playwright": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright-core": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/plur": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", + "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", + "license": "MIT", + "dependencies": { + "irregular-plurals": "^3.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-import": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.1.tgz", + "integrity": "sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "license": "MIT" + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "name": "wp-prettier", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz", + "integrity": "sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-agent/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==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/puppeteer-core": { + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", + "integrity": "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1367902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/puppeteer-core/node_modules/devtools-protocol": { + "version": "0.0.1367902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", + "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", + "license": "BSD-3-Clause" + }, + "node_modules/puppeteer-core/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==", + "license": "MIT" + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-is-18": { + "name": "react-is", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-is-19": { + "name": "react-is", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz", + "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.2.tgz", + "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/requestidlecallback": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz", + "integrity": "sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/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==", + "license": "MIT" + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "license": "MIT", + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-bin": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/resolve-bin/-/resolve-bin-0.4.3.tgz", + "integrity": "sha512-9u8TMpc+SEHXxQXblXHz5yRvRZERkCZimFN9oz85QI3uhkh7nqfjm6OGTLg+8vucpXGcY4jLK6WkylPmt7GSvw==", + "license": "MIT", + "dependencies": { + "find-parent-dir": "~0.3.0" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", + "license": "MIT", + "dependencies": { + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robots-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", + "integrity": "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "license": "MIT" + }, + "node_modules/rtlcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-con": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.2.12.tgz", + "integrity": "sha512-5257ILMYIF4RztL9uoZ7V9Q97zHtNHn5bN3NobeAnzB1P3ASLgg8qocM2u+R18ttp+VEM78N2LK8XcNVtnSRrg==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~3.0.0", + "minimist": "^1.2.8", + "strip-json-comments": "~3.1.1" + }, + "bin": { + "run-con": "cli.js" + } + }, + "node_modules/run-con/node_modules/ini": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", + "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.102.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.102.0.tgz", + "integrity": "sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-loader": { + "version": "16.0.8", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.8.tgz", + "integrity": "sha512-hcov4ZwZJIGbEuyNr9EmiTmZueyrxSToE6GOzoZnq5JM7ecRO7ttyvilPn+VmRsqiP16+VYZzVnGZj/hzZgKBA==", + "license": "MIT", + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "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==", + "license": "MIT", + "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/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "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==", + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shallow-clone/node_modules/kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", + "license": "MIT", + "dependencies": { + "is-buffer": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shallow-clone/node_modules/lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "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.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/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==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawnd": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-10.1.4.tgz", + "integrity": "sha512-drqHc0mKJmtMsiGMOCwzlc5eZ0RPtRvT7tQAluW2A0qUc0G7TQ8KLcn3E6K5qzkLkH2UkS3nYQiVGULvvsD9dw==", + "license": "MIT", + "dependencies": { + "signal-exit": "^4.1.0", + "tree-kill": "^1.2.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/spawnd/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/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==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.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==", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "license": "CC0-1.0" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/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==", + "license": "MIT" + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/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==", + "license": "MIT" + }, + "node_modules/speedline-core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", + "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "image-ssim": "^0.2.0", + "jpeg-js": "^0.4.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamx": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.0.tgz", + "integrity": "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/strnum": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz", + "integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/stubborn-fs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-2.0.0.tgz", + "integrity": "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==", + "license": "MIT", + "dependencies": { + "stubborn-utils": "^1.0.1" + } + }, + "node_modules/stubborn-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stubborn-utils/-/stubborn-utils-1.0.2.tgz", + "integrity": "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==", + "license": "MIT" + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "license": "ISC" + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/stylelint": { + "version": "16.26.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz", + "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-syntax-patches-for-csstree": "^1.0.19", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3", + "@csstools/selector-specificity": "^5.0.0", + "@dual-bundle/import-meta-resolve": "^4.2.1", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.3", + "css-tree": "^3.1.0", + "debug": "^4.4.3", + "fast-glob": "^3.3.3", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^11.1.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^7.0.5", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.37.0", + "mathml-tag-names": "^2.1.3", + "meow": "^13.2.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.5.6", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.1.0", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "supports-hyperlinks": "^3.2.0", + "svg-tags": "^1.0.0", + "table": "^6.9.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", + "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "license": "MIT", + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.1", + "stylelint-scss": "^6.4.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.6.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-scss": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz", + "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.1", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.37.0", + "mdn-data": "^2.25.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-selector-parser": "^7.1.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.8.2" + } + }, + "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stylelint/node_modules/@csstools/media-query-list-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/stylelint/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/stylelint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/stylelint/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "license": "MIT" + }, + "node_modules/stylelint/node_modules/cosmiconfig": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/stylelint/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", + "license": "MIT", + "dependencies": { + "flat-cache": "^6.1.23" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", + "license": "MIT", + "dependencies": { + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" + } + }, + "node_modules/stylelint/node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/stylelint/node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/stylelint/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylelint/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/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==", + "license": "MIT" + }, + "node_modules/stylelint/node_modules/postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stylelint/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/stylelint/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" + }, + "node_modules/svgo": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.4.tgz", + "integrity": "sha512-GsNRis4e8jxn2Y9ENz/8lbJ93CstG8svtMnuRaHbiF2LTJ5tK0/q3t/URPq9Zc7zVWBJnNnJMIp6bevK7bSmNg==", + "license": "MIT", + "dependencies": { + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/svgo/node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "license": "CC0-1.0" + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "license": "MIT" + }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/tannin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", + "integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==", + "license": "MIT", + "dependencies": { + "@tannin/plural-forms": "^1.1.0" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar-fs": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.3.tgz", + "integrity": "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", + "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar-stream/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/terser": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.2.tgz", + "integrity": "sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">= 0.4" + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/is-unsafe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.0.tgz", - "integrity": "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-decoder/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true } - ], + } + }, + "node_modules/third-party-web": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.27.0.tgz", + "integrity": "sha512-h0JYX+dO2Zr3abCQpS6/uFjujaOjA1DyDzGQ41+oFn9VW/ARiq9g5ln7qEP9+BTzDpOMyIfsfj4OvfgXAsMUSA==", "license": "MIT" }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "license": "MIT" }, - "node_modules/isomorphic-git": { - "version": "1.37.6", - "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.37.6.tgz", - "integrity": "sha512-qr1NFCPsVTZ6YGqTXw0CzamnsHyH9QQ1OTEfeXIweSljRUMzuHFCJdUn0wc6OcjtTDns6knxjPb7N6LmJeftOA==", + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { - "async-lock": "^1.4.1", - "clean-git-ref": "^2.0.1", - "crc-32": "^1.2.0", - "diff3": "0.0.3", - "ignore": "^5.1.4", - "minimisted": "^2.0.0", - "pako": "^1.0.10", - "pify": "^4.0.1", - "readable-stream": "^4.0.0", - "sha.js": "^2.4.12", - "simple-get": "^4.0.1" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, - "bin": { - "isogit": "cli.cjs" + "engines": { + "node": ">=12.0.0" }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "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/tinyglobby/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.10.tgz", + "integrity": "sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==", "license": "MIT" }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "node_modules/tldts-icann": { + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts-icann/-/tldts-icann-7.4.10.tgz", + "integrity": "sha512-JrzJnTNDURpnyPCf/b0bq/mAiQhPcNwkwpfO67M0nECzVzSIuCFN+EYjqnEjnmO60nPRabS3zIFChbwPp/Q+Lg==", + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.10" + } + }, + "node_modules/tldts/node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "license": "MIT" }, - "node_modules/jsonfile": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", - "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "tmp": "^0.2.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause" + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 0.4" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", - "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { - "jws": "^4.0.1", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">=18" } }, - "node_modules/jsonwebtoken/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==", - "license": "MIT" + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } }, - "node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/jws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", - "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "license": "MIT", "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } }, - "node_modules/lru-cache": { - "name": "@wolfy1339/lru-cache", - "version": "11.0.2-patch.1", - "resolved": "https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz", - "integrity": "sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==", - "license": "ISC", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", "engines": { - "node": "18 >=18.20 || 20 || >=22" + "node": ">=4" } }, - "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==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8.0" } }, - "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==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "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==", - "license": "MIT", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, "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==", + "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==", "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, "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==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "license": "MIT", - "bin": { - "mime": "cli.js" + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": ">=4" + "node": ">= 0.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==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/typed-query-selector": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", + "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.66.0.tgz", + "integrity": "sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.66.0", + "@typescript-eslint/parser": "8.66.0", + "@typescript-eslint/typescript-estree": "8.66.0", + "@typescript-eslint/utils": "8.66.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimisted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", - "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "license": "MIT", "dependencies": { - "minimist": "^1.2.5" + "buffer": "^5.2.1", + "through": "^2.3.8" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, - "node_modules/nan": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", - "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", + "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==", "license": "MIT" }, - "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==", + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "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==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4" } }, - "node_modules/octokit": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/octokit/-/octokit-3.1.2.tgz", - "integrity": "sha512-MG5qmrTL5y8KYwFgE1A4JWmgfQBaIETE/lOlfwNYx1QOtCQHGVxkRJmdUJltFc1HVn73d61TlMhMyNTOtMl+ng==", + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "license": "MIT", - "dependencies": { - "@octokit/app": "^14.0.2", - "@octokit/core": "^5.0.0", - "@octokit/oauth-app": "^6.0.0", - "@octokit/plugin-paginate-graphql": "^4.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0", - "@octokit/plugin-retry": "^6.0.0", - "@octokit/plugin-throttling": "^8.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0" - }, "engines": { - "node": ">= 18" + "node": ">=4" } }, - "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==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", + "node_modules/universal-github-app-jwt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.2.0.tgz", + "integrity": "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g==", + "license": "MIT", "dependencies": { - "wrappy": "1" + "@types/jsonwebtoken": "^9.0.0", + "jsonwebtoken": "^9.0.2" } }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "license": "(MIT AND Zlib)" + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "license": "ISC" }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/path-expression-matcher": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", - "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.0.tgz", + "integrity": "sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==", "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, { "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "engines": { - "node": ">=14.0.0" + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/path-to-regexp": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", - "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", - "license": "MIT" - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "tslib": "^2.0.3" } }, - "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==", + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "tslib": "^2.0.3" } }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.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==", + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } } }, - "node_modules/qs": { - "version": "6.15.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", - "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", - "license": "BSD-3-Clause", + "node_modules/url-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.1", - "side-channel": "^1.1.1" - }, - "engines": { - "node": ">=0.6" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "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==", + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "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==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4.0" } }, - "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==", + "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==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.12.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" - } - ], - "license": "MIT" + "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==", + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" + "node_modules/validate-npm-package-license/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==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, - "node_modules/sax": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", - "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", - "license": "BlueOak-1.0.0", + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "license": "ISC", "engines": { - "node": ">=11.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "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==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.8" } }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" } }, - "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==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "node_modules/wait-on": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.5.tgz", + "integrity": "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" + "axios": "^1.12.1", + "joi": "^18.0.1", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" }, "engines": { - "node": ">= 0.8.0" + "node": ">=12.0.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==", + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, + "node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "license": "MIT", "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" + "graceful-fs": "^4.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } }, - "node_modules/sha.js": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", - "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", - "license": "(MIT AND BSD-3-Clause)", + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", + "license": "Apache-2.0" + }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", + "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", + "license": "Apache-2.0" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack": { + "version": "5.109.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.109.2.tgz", + "integrity": "sha512-U9/cvLzxObKNEZ9+TtdqrHM5/9z3lgl2c+c4BzbqGxFQvQvBAq87yql5A8pQ+rrMbS496MZJeF5enVBndIy2hw==", + "license": "MIT", "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1", - "to-buffer": "^1.2.0" + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.24.4", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "graceful-fs": "^4.2.11", + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.6.1", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.1" }, "bin": { - "sha.js": "bin.js" + "webpack": "bin/webpack.js" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/side-channel": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", - "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4", - "side-channel-list": "^1.0.1", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": ">= 0.4" + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", + "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">= 0.4" + "node": ">=14.15.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "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==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "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==", + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", "license": "MIT", "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" + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "webpack-cli": { + "optional": true } - ], - "license": "MIT" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "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/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/webpack-dev-server/node_modules/ipaddr.js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz", + "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 10" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10.0.0" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/webpack-merge/node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/strnum": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.1.tgz", - "integrity": "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], + "node_modules/webpack-merge/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "license": "MIT", "dependencies": { - "anynum": "^1.0.1" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tmp": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", - "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "node_modules/webpack-merge/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "license": "MIT", "engines": { - "node": ">=14.14" + "node": ">=0.10.0" } }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "node_modules/webpack-merge/node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "license": "MIT", "dependencies": { - "tmp": "^0.2.0" + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/to-buffer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", - "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "node_modules/webpack-sources": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz", + "integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz", + "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==", + "license": "Apache-2.0", "dependencies": { - "isarray": "^2.0.5", - "safe-buffer": "^5.2.1", - "typed-array-buffer": "^1.0.3" + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" }, "engines": { - "node": ">= 0.4" + "node": ">=0.8.0" } }, - "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==", - "license": "MIT", + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", "engines": { - "node": ">=0.6" + "node": ">=0.8.0" } }, - "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==", + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "iconv-lite": "0.6.3" }, "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/undici-types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", - "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", - "license": "MIT" + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, - "node_modules/universal-github-app-jwt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.2.0.tgz", - "integrity": "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g==", + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "license": "MIT", "dependencies": { - "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.2" + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "license": "ISC" + "node_modules/when-exit": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.5.tgz", + "integrity": "sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==", + "license": "MIT" }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, "engines": { - "node": ">= 10.0.0" + "node": ">= 8" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wasm-feature-detect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", - "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", - "license": "Apache-2.0" - }, "node_modules/which-typed-array": { "version": "1.1.22", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", @@ -2897,6 +23205,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "license": "MIT" + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -2920,6 +23243,19 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/ws": { "version": "8.21.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", @@ -2941,6 +23277,27 @@ } } }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/xml-naming": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", @@ -2978,6 +23335,21 @@ "node": ">=4.0" } }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2987,6 +23359,21 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -3014,6 +23401,63 @@ "node": ">=12" } }, + "node_modules/yarn": { + "version": "1.22.22", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", + "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", + "hasInstallScript": true, + "license": "BSD-2-Clause", + "bin": { + "yarn": "bin/yarn.js", + "yarnpkg": "bin/yarn.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, "node_modules/zstddec": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.2.0.tgz", diff --git a/.github/docs-playground-preview/package.json b/.github/docs-playground-preview/package.json index e2e7db936c1ce..0a94f575c3772 100644 --- a/.github/docs-playground-preview/package.json +++ b/.github/docs-playground-preview/package.json @@ -11,6 +11,9 @@ "test": "node --test ../scripts/docs-playground-preview/test/*.test.mjs" }, "dependencies": { - "@wp-playground/cli": "3.1.48" + "@wordpress/i18n": "6.24.0", + "@wordpress/scripts": "32.6.0", + "@wp-playground/cli": "3.1.48", + "yarn": "1.22.22" } } diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index 72cfd4c5f36e9..9ddac2016bcbc 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -49,7 +49,14 @@ export function validateDependencies( dependencies ) { ); assertObject( dependencies.toolchain, 'toolchain' ); assertObject( dependencies.playground, 'playground' ); - for ( const name of [ 'nodeVersion', 'npmVersion', 'composerVersion' ] ) { + for ( const name of [ + 'nodeVersion', + 'npmVersion', + 'composerVersion', + 'yarnVersion', + 'wpScriptsVersion', + 'wpI18nVersion', + ] ) { if ( ! VERSION.test( dependencies.toolchain[ name ] ) ) { throw new Error( `toolchain.${ name } must be an exact version.` ); } diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 3eb3461c06c26..a9d3df95822fc 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -42,6 +42,18 @@ test( 'the checked-in dependency manifest is valid', async () => { packageManifest.dependencies[ '@wp-playground/cli' ], dependencies.playground.cliVersion ); + assert.equal( + packageManifest.dependencies.yarn, + dependencies.toolchain.yarnVersion + ); + assert.equal( + packageManifest.dependencies[ '@wordpress/scripts' ], + dependencies.toolchain.wpScriptsVersion + ); + assert.equal( + packageManifest.dependencies[ '@wordpress/i18n' ], + dependencies.toolchain.wpI18nVersion + ); } ); test( 'dependency repositories and commits are fixed', async () => { @@ -61,7 +73,14 @@ test( 'dependency repositories and commits are fixed', async () => { } ); test( 'toolchain versions are exact and required', async () => { - for ( const name of [ 'nodeVersion', 'npmVersion', 'composerVersion' ] ) { + for ( const name of [ + 'nodeVersion', + 'npmVersion', + 'composerVersion', + 'yarnVersion', + 'wpScriptsVersion', + 'wpI18nVersion', + ] ) { const dependencies = await manifest(); delete dependencies.toolchain[ name ]; assert.throws( From 62dc2576aa9c24c3943241d7573c92e70e4f317d Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 11:02:55 +0400 Subject: [PATCH 04/59] Build/Test Tools: Cache the Code Reference site base Rebuilding themes, plugins, parser dependencies, and the empty DevHub site on every preview wastes the expensive half of the job. Build that state once under the exact cache key and write the completion marker last. The untrimmed base was 98,884,490 bytes. Drop unused CJK preview fonts before packaging; the real cold build falls to 43,224,482 bytes and leaves room for the reference import without weakening the 100 MiB limit. --- .../docs-playground-preview/lib/archive.mjs | 55 ++++ .../docs-playground-preview/lib/base.mjs | 297 ++++++++++++++++++ .../php/base-policy.php | 40 +++ .../php/configure-base.php | 89 ++++++ .../test/base.test.mjs | 152 +++++++++ .gitignore | 1 + 6 files changed, 634 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/archive.mjs create mode 100644 .github/scripts/docs-playground-preview/lib/base.mjs create mode 100644 .github/scripts/docs-playground-preview/php/base-policy.php create mode 100644 .github/scripts/docs-playground-preview/php/configure-base.php create mode 100644 .github/scripts/docs-playground-preview/test/base.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/archive.mjs b/.github/scripts/docs-playground-preview/lib/archive.mjs new file mode 100644 index 0000000000000..eba012e219dd3 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/archive.mjs @@ -0,0 +1,55 @@ +import { cp, mkdir, mkdtemp, rm } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; + +import { run } from './process.mjs'; + +const DEFAULT_EXCLUDES = [ '.git', '.github', 'node_modules', 'tests' ]; + +function isExcluded( relative, excludes ) { + return excludes.some( + ( excluded ) => + relative === excluded || relative.startsWith( `${ excluded }/` ) + ); +} + +export async function copyDirectory( source, destination, excludes = [] ) { + const root = path.resolve( source ); + await mkdir( destination, { recursive: true } ); + await cp( root, destination, { + recursive: true, + filter: ( filename ) => { + const relative = path.relative( root, filename ); + return ! relative || ! isExcluded( relative, excludes ); + }, + } ); +} + +export async function zipDirectory( + source, + output, + rootName, + runImplementation = run +) { + const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-zip-' ) ); + const target = rootName === '.' ? temporary : path.join( temporary, rootName ); + try { + await copyDirectory( source, target, DEFAULT_EXCLUDES ); + await rm( output, { force: true } ); + await runImplementation( 'zip', [ '-rq', path.resolve( output ), '.' ], { + cwd: temporary, + label: `package ${ rootName }`, + } ); + } finally { + await rm( temporary, { recursive: true, force: true } ); + } +} + +export async function downloadFile( url, output, runImplementation = run ) { + await mkdir( path.dirname( output ), { recursive: true } ); + await runImplementation( + 'curl', + [ '--fail', '--location', '--output', output, url ], + { label: `download ${ url }` } + ); +} diff --git a/.github/scripts/docs-playground-preview/lib/base.mjs b/.github/scripts/docs-playground-preview/lib/base.mjs new file mode 100644 index 0000000000000..12e776f82f0f4 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/base.mjs @@ -0,0 +1,297 @@ +import { fileURLToPath } from 'node:url'; +import { + cp, + mkdir, + readFile, + rm, + writeFile, +} from 'node:fs/promises'; +import path from 'node:path'; + +import { copyDirectory, downloadFile, zipDirectory } from './archive.mjs'; +import { acquireRepositories, exists } from './files.mjs'; +import { run } from './process.mjs'; + +const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); +const SCRIPT_ROOT = path.dirname( LIBRARY_ROOT ); +const TOOLING_ROOT = path.resolve( LIBRARY_ROOT, '../../../docs-playground-preview' ); +const PHP_ROOT = path.join( SCRIPT_ROOT, 'php' ); + +function executable( name ) { + return path.join( + TOOLING_ROOT, + 'node_modules/.bin', + process.platform === 'win32' ? `${ name }.cmd` : name + ); +} + +export function dependencyBuildPlan( roots, composer ) { + const nodePath = path.join( TOOLING_ROOT, 'node_modules' ); + const wpScriptsEnvironment = { NODE_PATH: nodePath }; + return [ + { + command: 'php', + args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + cwd: roots.phpdocParser, + label: 'install phpdoc-parser dependencies', + }, + { + command: executable( 'yarn' ), + args: [ 'install', '--frozen-lockfile', '--ignore-scripts' ], + cwd: roots.wporgParent2021, + label: 'install wporg-parent-2021 dependencies', + }, + { + command: executable( 'yarn' ), + args: [ 'build:theme' ], + cwd: roots.wporgParent2021, + label: 'build wporg-parent-2021', + }, + { + command: executable( 'wp-scripts' ), + args: [ 'build' ], + cwd: roots.wporgDeveloperTheme, + env: wpScriptsEnvironment, + label: 'build wporg-developer-2023', + }, + { + command: 'npm', + args: [ 'ci', '--ignore-scripts', '--no-audit', '--no-fund' ], + cwd: roots.wporgMuPlugins, + label: 'install wporg-mu-plugins dependencies', + }, + { + command: 'php', + args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + cwd: roots.wporgMuPlugins, + label: 'install wporg-mu-plugins Composer dependencies', + }, + { + command: 'npm', + args: [ 'run', 'build' ], + cwd: roots.wporgMuPlugins, + label: 'build wporg-mu-plugins', + }, + { + command: 'php', + args: [ composer, 'config', 'allow-plugins.composer/installers', 'true' ], + cwd: roots.postsToPosts, + label: 'configure posts-to-posts installer', + }, + { + command: 'php', + args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + cwd: roots.postsToPosts, + label: 'install posts-to-posts dependencies', + }, + { + command: executable( 'wp-scripts' ), + args: [ 'build' ], + cwd: roots.codeSyntaxBlock, + env: wpScriptsEnvironment, + label: 'build code-syntax-block', + }, + ]; +} + +function bundled( resourcePath ) { + return { resource: 'bundled', path: resourcePath }; +} + +export function createInvariantBaseBlueprint( inputs ) { + return { + $schema: inputs.dependencies.playground.blueprintSchema, + meta: { + title: 'WordPress Core Code Reference invariant base', + author: 'WordPress', + description: 'Pinned DevHub dependencies with an empty reference index.', + }, + preferredVersions: { + php: inputs.dependencies.playground.phpVersion, + wp: inputs.wordpress.version, + }, + landingPage: '/reference/', + login: false, + features: { networking: false }, + extraLibraries: [ 'wp-cli' ], + steps: [ + { + step: 'writeFile', + path: '/wordpress/wp-content/mu-plugins/000-docs-preview-build.php', + data: bundled( 'php/base-policy.php' ), + }, + { + step: 'unzip', + zipFile: bundled( 'bundles/wporg-mu-plugins.zip' ), + extractToPath: '/wordpress/wp-content/mu-plugins', + }, + { + step: 'installTheme', + themeData: bundled( 'bundles/wporg-parent-2021.zip' ), + ifAlreadyInstalled: 'overwrite', + }, + { + step: 'installTheme', + themeData: bundled( 'bundles/wporg-developer-2023.zip' ), + ifAlreadyInstalled: 'overwrite', + }, + ...[ + 'code-syntax-block', + 'posts-to-posts', + 'phpdoc-parser', + ].map( ( plugin ) => ( { + step: 'unzip', + zipFile: bundled( `bundles/${ plugin }.zip` ), + extractToPath: '/wordpress/wp-content/plugins', + } ) ), + { + step: 'writeFile', + path: '/tmp/docs-preview-configure-base.php', + data: bundled( 'php/configure-base.php' ), + }, + { + step: 'wp-cli', + command: 'wp eval-file /tmp/docs-preview-configure-base.php', + }, + ], + }; +} + +export async function prunePreviewFonts( muPlugins ) { + await rm( path.join( muPlugins, 'global-fonts/NotoSerif' ), { + recursive: true, + force: true, + } ); + const stylesheet = path.join( muPlugins, 'global-fonts/style.css' ); + const css = await readFile( stylesheet, 'utf8' ); + await writeFile( + stylesheet, + css + .split( '\n' ) + .filter( ( line ) => ! line.includes( '@import "./NotoSerif/' ) ) + .join( '\n' ) + ); +} + +async function ensureComposer( inputs, tools, runImplementation ) { + const version = inputs.dependencies.toolchain.composerVersion; + const composer = path.join( tools, `composer-${ version }.phar` ); + if ( ! ( await exists( composer ) ) ) { + await downloadFile( + `https://getcomposer.org/download/${ version }/composer.phar`, + composer, + runImplementation + ); + } + return composer; +} + +function repositoryRoots( upstreams, inputs ) { + const root = ( name ) => path.join( upstreams, name ); + const selected = ( name ) => + path.join( root( name ), inputs.dependencies.repositories[ name ].path ); + return { + phpdocParser: selected( 'phpdocParser' ), + wporgDeveloperTheme: selected( 'wporgDeveloper' ), + wporgParent2021: root( 'wporgParent2021' ), + wporgParentTheme: selected( 'wporgParent2021' ), + wporgMuPlugins: root( 'wporgMuPlugins' ), + wporgMuPluginsFiles: selected( 'wporgMuPlugins' ), + postsToPosts: selected( 'postsToPosts' ), + codeSyntaxBlock: selected( 'codeSyntaxBlock' ), + }; +} + +async function buildInvariantBase( inputs, options ) { + const runImplementation = options.runImplementation || run; + const work = path.join( inputs.cacheDirectory, 'work' ); + const upstreams = path.join( work, 'upstreams' ); + const bundles = path.join( work, 'bundles' ); + const tools = path.join( work, 'tools' ); + await mkdir( bundles, { recursive: true } ); + await acquireRepositories( + inputs.dependencies.repositories, + upstreams, + runImplementation + ); + const roots = repositoryRoots( upstreams, inputs ); + const composer = await ensureComposer( inputs, tools, runImplementation ); + for ( const task of dependencyBuildPlan( roots, composer ) ) { + await runImplementation( task.command, task.args, task ); + } + await prunePreviewFonts( roots.wporgMuPluginsFiles ); + + for ( const [ name, source, rootName ] of [ + [ 'wporg-parent-2021', roots.wporgParentTheme, 'wporg-parent-2021' ], + [ 'wporg-developer-2023', roots.wporgDeveloperTheme, 'wporg-developer-2023' ], + [ 'wporg-mu-plugins', roots.wporgMuPluginsFiles, '.' ], + [ 'posts-to-posts', roots.postsToPosts, 'posts-to-posts' ], + [ 'phpdoc-parser', roots.phpdocParser, 'phpdoc-parser' ], + [ 'code-syntax-block', roots.codeSyntaxBlock, 'code-syntax-block' ], + ] ) { + await zipDirectory( + source, + path.join( bundles, `${ name }.zip` ), + rootName, + runImplementation + ); + } + + await mkdir( path.join( work, 'php' ), { recursive: true } ); + for ( const script of [ 'base-policy.php', 'configure-base.php' ] ) { + await cp( path.join( PHP_ROOT, script ), path.join( work, 'php', script ) ); + } + const blueprint = path.join( work, 'base-blueprint.json' ); + await writeFile( + blueprint, + `${ JSON.stringify( createInvariantBaseBlueprint( inputs ), null, 2 ) }\n` + ); + await runImplementation( + options.playgroundCli || executable( 'wp-playground-cli' ), + [ + 'build-snapshot', + '--php', + inputs.dependencies.playground.phpVersion, + '--wp', + inputs.wordpress.version, + '--blueprint', + blueprint, + '--blueprint-may-read-adjacent-files', + '--outfile', + path.join( inputs.cacheDirectory, 'base.zip' ), + '--verbosity', + 'normal', + ], + { label: 'build invariant Playground base' } + ); + await copyDirectory( roots.phpdocParser, path.join( inputs.cacheDirectory, 'parser' ), [ '.git' ] ); + await rm( work, { recursive: true, force: true } ); +} + +export async function ensureInvariantBase( inputs, options = {} ) { + const markerFile = path.join( inputs.cacheDirectory, 'base.json' ); + if ( await exists( markerFile ) ) { + const marker = JSON.parse( await readFile( markerFile, 'utf8' ) ); + if ( + marker.cacheKey === inputs.cacheKey && + ( await exists( path.join( inputs.cacheDirectory, 'base.zip' ) ) ) && + ( await exists( + path.join( inputs.cacheDirectory, 'parser/generate-json-manually.php' ) + ) ) + ) { + return { ...marker, cacheHit: true }; + } + } + await rm( inputs.cacheDirectory, { recursive: true, force: true } ); + await mkdir( inputs.cacheDirectory, { recursive: true } ); + await ( options.buildImplementation || buildInvariantBase )( inputs, options ); + const marker = { + schemaVersion: 1, + cacheKey: inputs.cacheKey, + wordpress: inputs.wordpress, + dependencyDigest: inputs.cacheInputs.dependencyDigest, + harnessDigest: inputs.cacheInputs.harnessDigest, + }; + await writeFile( markerFile, `${ JSON.stringify( marker, null, 2 ) }\n` ); + return { ...marker, cacheHit: false }; +} diff --git a/.github/scripts/docs-playground-preview/php/base-policy.php b/.github/scripts/docs-playground-preview/php/base-policy.php new file mode 100644 index 0000000000000..aa8eb49b59d31 --- /dev/null +++ b/.github/scripts/docs-playground-preview/php/base-policy.php @@ -0,0 +1,40 @@ + time(), + 'checked' => array(), + 'no_update' => array(), + 'response' => array(), + 'translations' => array(), + 'updates' => array(), + ); + } + ); +} diff --git a/.github/scripts/docs-playground-preview/php/configure-base.php b/.github/scripts/docs-playground-preview/php/configure-base.php new file mode 100644 index 0000000000000..6b866c0b3ca72 --- /dev/null +++ b/.github/scripts/docs-playground-preview/php/configure-base.php @@ -0,0 +1,89 @@ +get_error_message() ); + } +} + +sort( $active_plugins ); +update_option( 'active_plugins', $active_plugins ); +switch_theme( 'wporg-developer-2023' ); +update_option( 'permalink_structure', '/%year%/%monthnum%/%postname%/' ); + +$ensure_page = static function( $slug, $title ) { + $page = get_page_by_path( $slug, OBJECT, 'page' ); + if ( $page ) { + return $page->ID; + } + $result = wp_insert_post( + array( + 'post_type' => 'page', + 'post_title' => $title, + 'post_status' => 'publish', + 'post_name' => $slug, + ), + true + ); + if ( is_wp_error( $result ) ) { + throw new RuntimeException( $result->get_error_message() ); + } + return $result; +}; + +update_option( 'show_on_front', 'page' ); +update_option( 'page_on_front', $ensure_page( 'home', 'Home' ) ); +$ensure_page( 'reference', 'Reference' ); + +$navigation = ''; +$existing = get_page_by_path( 'reference-api-menu', OBJECT, 'wp_navigation' ); +$nav_args = array( + 'post_title' => 'Reference API Menu', + 'post_name' => 'reference-api-menu', + 'post_type' => 'wp_navigation', + 'post_status' => 'publish', + 'post_content' => $navigation, +); +if ( $existing ) { + $nav_args['ID'] = $existing->ID; + $result = wp_update_post( $nav_args, true ); +} else { + $nav_args['import_id'] = 148843; + $result = wp_insert_post( $nav_args, true ); +} +if ( is_wp_error( $result ) ) { + throw new RuntimeException( $result->get_error_message() ); +} + +global $wpdb; +$reference_types = array( + 'wp-parser-class', + 'wp-parser-function', + 'wp-parser-hook', + 'wp-parser-method', + 'wp-parser-source-file', +); +$placeholders = implode( ',', array_fill( 0, count( $reference_types ), '%s' ) ); +$count = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type IN ({$placeholders})", + $reference_types + ) +); +if ( 0 !== (int) $count ) { + throw new RuntimeException( 'Invariant base contains generated reference posts.' ); +} + +flush_rewrite_rules( false ); diff --git a/.github/scripts/docs-playground-preview/test/base.test.mjs b/.github/scripts/docs-playground-preview/test/base.test.mjs new file mode 100644 index 0000000000000..faad291f06a81 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/base.test.mjs @@ -0,0 +1,152 @@ +import assert from 'node:assert/strict'; +import { mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + createInvariantBaseBlueprint, + dependencyBuildPlan, + ensureInvariantBase, + prunePreviewFonts, +} from '../lib/base.mjs'; +import { zipDirectory } from '../lib/archive.mjs'; +import { run } from '../lib/process.mjs'; + +function inputs( cacheDirectory ) { + return { + cacheKey: 'docs-preview-base-v1-' + 'a'.repeat( 64 ), + cacheDirectory, + cacheInputs: { + dependencyDigest: 'b'.repeat( 64 ), + harnessDigest: 'c'.repeat( 64 ), + }, + wordpress: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + dependencies: { + playground: { + blueprintSchema: 'https://playground.wordpress.net/blueprint-schema.json', + phpVersion: '8.4', + }, + }, + }; +} + +test( 'the invariant Blueprint installs dependencies without importing source', () => { + const blueprint = createInvariantBaseBlueprint( inputs( '/cache' ) ); + assert.deepEqual( blueprint.preferredVersions, { + php: '8.4', + wp: '7.2-beta1', + } ); + assert.deepEqual( blueprint.features, { networking: false } ); + assert.equal( blueprint.login, false ); + assert.equal( + blueprint.steps.some( ( step ) => /import|reference\.json/.test( JSON.stringify( step ) ) ), + false + ); + assert.deepEqual( + blueprint.steps + .filter( ( step ) => step.step === 'installTheme' ) + .map( ( step ) => step.themeData.path ), + [ + 'bundles/wporg-parent-2021.zip', + 'bundles/wporg-developer-2023.zip', + ] + ); +} ); + +test( 'dependency build plan uses pinned harness tools and upstream locks', () => { + const roots = { + phpdocParser: '/repos/parser', + wporgParent2021: '/repos/parent', + wporgDeveloperTheme: '/repos/developer/theme', + wporgMuPlugins: '/repos/mu', + postsToPosts: '/repos/p2p', + codeSyntaxBlock: '/repos/syntax', + }; + const plan = dependencyBuildPlan( roots, '/tools/composer.phar' ); + assert.equal( plan.length, 10 ); + assert.deepEqual( plan[ 0 ].args.slice( 0, 2 ), [ + '/tools/composer.phar', + 'install', + ] ); + assert.match( plan[ 1 ].command, /node_modules\/\.bin\/yarn$/ ); + assert.deepEqual( plan[ 1 ].args, [ + 'install', + '--frozen-lockfile', + '--ignore-scripts', + ] ); + assert.match( plan[ 3 ].command, /node_modules\/\.bin\/wp-scripts$/ ); + assert.deepEqual( plan[ 4 ].args.slice( 0, 2 ), [ 'ci', '--ignore-scripts' ] ); +} ); + +test( 'the invariant base marker is written last and enables exact reuse', async () => { + const cache = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-base-' ) ); + const resolved = inputs( path.join( cache, 'entry' ) ); + let builds = 0; + const buildImplementation = async ( current ) => { + builds++; + await writeFile( path.join( current.cacheDirectory, 'base.zip' ), 'base' ); + await mkdir( path.join( current.cacheDirectory, 'parser' ) ); + await writeFile( + path.join( current.cacheDirectory, 'parser/generate-json-manually.php' ), + ' { + const policy = await readFile( + new URL( '../php/base-policy.php', import.meta.url ), + 'utf8' + ); + assert.doesNotMatch( policy, /DISALLOW_FILE_MODS|AUTOMATIC_UPDATER_DISABLED/ ); +} ); + +test( 'dependency bundles have the requested install root and omit build tools', async () => { + const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-bundle-' ) ); + const source = path.join( temporary, 'source' ); + await mkdir( path.join( source, 'node_modules' ), { recursive: true } ); + await writeFile( path.join( source, 'plugin.php' ), ' { + const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-fonts-' ) ); + const fonts = path.join( root, 'global-fonts' ); + await mkdir( path.join( fonts, 'NotoSerif' ), { recursive: true } ); + await writeFile( path.join( fonts, 'NotoSerif/font.woff2' ), 'large' ); + await writeFile( + path.join( fonts, 'style.css' ), + '@import "./NotoSerif/NotoSerifJP/style.css";\nbody { color: black; }\n' + ); + await prunePreviewFonts( root ); + await assert.rejects( readFile( path.join( fonts, 'NotoSerif/font.woff2' ) ) ); + assert.equal( + await readFile( path.join( fonts, 'style.css' ), 'utf8' ), + 'body { color: black; }\n' + ); +} ); diff --git a/.gitignore b/.gitignore index 15876fa47fee8..98bd3613b9f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ wp-tests-config.php /tests/performance/**/*.test.results.json /src/.wp-tests-version /node_modules +/.github/docs-playground-preview/node_modules /npm-debug.log /build /gutenberg From b97d59fb235a3797f244643985ca5931dd2e141d Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 11:09:26 +0400 Subject: [PATCH 05/59] Build/Test Tools: Generate Code Reference parser data The preview must parse the exact Core checkout without loading it. Stage only eligible PHP, run the pinned parser, and normalize source roots for the later import. Current trunk yields 1,318 files, 764 classes, 7,316 methods, 4,386 functions, 1,031 hooks, and 2,397 filters. Fixed low floors catch collapse without pretending counts are stable. Empty output is advisory metadata, not a publisher candidate. --- .../docs-playground-preview/dependencies.json | 2 +- .../docs-playground-preview/lib/parser.mjs | 99 +++++++++++++ .../test/parser.test.mjs | 130 ++++++++++++++++++ 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 .github/scripts/docs-playground-preview/lib/parser.mjs create mode 100644 .github/scripts/docs-playground-preview/test/parser.test.mjs diff --git a/.github/docs-playground-preview/dependencies.json b/.github/docs-playground-preview/dependencies.json index b8ffebe75e70d..5745399688474 100644 --- a/.github/docs-playground-preview/dependencies.json +++ b/.github/docs-playground-preview/dependencies.json @@ -56,7 +56,7 @@ "minimumSymbols": { "classes": 400, "methods": 3000, - "functions": 1200, + "functions": 1800, "hooks": 600, "filters": 1000 }, diff --git a/.github/scripts/docs-playground-preview/lib/parser.mjs b/.github/scripts/docs-playground-preview/lib/parser.mjs new file mode 100644 index 0000000000000..fc9fccef53b26 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/parser.mjs @@ -0,0 +1,99 @@ +import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import path from 'node:path'; + +import { stageCorePhp } from './files.mjs'; +import { run } from './process.mjs'; + +const HOOK_TYPE = /^(?:action|filter)(?:_(?:deprecated|reference))?$/; + +function hooksIn( value ) { + return Array.isArray( value?.hooks ) ? value.hooks : []; +} + +function countHooks( hooks, counts ) { + for ( const hook of hooks ) { + if ( ! hook || typeof hook !== 'object' || ! HOOK_TYPE.test( hook.type ) ) { + throw new Error( 'Parser JSON contains a hook with an invalid type.' ); + } + if ( hook.type.startsWith( 'action' ) ) { + counts.hooks++; + } else { + counts.filters++; + } + } +} + +export function inspectParserRecords( records, minimumSymbols ) { + if ( ! Array.isArray( records ) ) { + throw new Error( 'Parser JSON must be an array.' ); + } + const counts = { + classes: 0, + methods: 0, + functions: 0, + hooks: 0, + filters: 0, + }; + for ( const record of records ) { + if ( ! record || typeof record !== 'object' || typeof record.path !== 'string' ) { + throw new Error( 'Parser JSON contains an invalid file record.' ); + } + if ( + record.path.startsWith( 'wp-content/plugins/' ) || + record.path.startsWith( 'wp-content/themes/' ) + ) { + throw new Error( `Parser JSON contains excluded source: ${ record.path }.` ); + } + const functions = Array.isArray( record.functions ) ? record.functions : []; + const classes = Array.isArray( record.classes ) ? record.classes : []; + counts.functions += functions.length; + counts.classes += classes.length; + for ( const item of functions ) { + countHooks( hooksIn( item ), counts ); + } + for ( const item of classes ) { + const methods = Array.isArray( item?.methods ) ? item.methods : []; + counts.methods += methods.length; + for ( const method of methods ) { + countHooks( hooksIn( method ), counts ); + } + } + countHooks( hooksIn( record ), counts ); + record.root = '/tmp/docs-preview-source'; + } + const failures = records.length === 0 ? [ 'Parser produced no file records.' ] : []; + failures.push( ...Object.entries( minimumSymbols ) + .filter( ( [ type, minimum ] ) => counts[ type ] < minimum ) + .map( + ( [ type, minimum ] ) => + `Parser produced ${ counts[ type ] } ${ type }; expected at least ${ minimum }.` + ) ); + return { records: records.length, counts, failures }; +} + +export async function generateParserJson( options ) { + const runImplementation = options.runImplementation || run; + const staged = await stageCorePhp( options.source, options.stagedSource ); + await mkdir( path.dirname( options.output ), { recursive: true } ); + await runImplementation( + 'php', + [ + '-d', + 'memory_limit=4G', + path.join( options.parser, 'generate-json-manually.php' ), + '-d', + options.stagedSource, + '-o', + options.output, + ], + { + capture: Boolean( options.logFile ), + logFile: options.logFile, + label: 'generate Code Reference parser JSON', + } + ); + const records = JSON.parse( await readFile( options.output, 'utf8' ) ); + const inspection = inspectParserRecords( records, options.minimumSymbols ); + await writeFile( options.output, `${ JSON.stringify( records ) }\n` ); + return { ...inspection, sourceFiles: staged.files }; +} diff --git a/.github/scripts/docs-playground-preview/test/parser.test.mjs b/.github/scripts/docs-playground-preview/test/parser.test.mjs new file mode 100644 index 0000000000000..187f8a9f8160c --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/parser.test.mjs @@ -0,0 +1,130 @@ +import assert from 'node:assert/strict'; +import { mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + generateParserJson, + inspectParserRecords, +} from '../lib/parser.mjs'; + +function records() { + return [ + { + path: 'wp-includes/example.php', + functions: [ + { + name: 'example', + hooks: [ { type: 'filter' }, { type: 'action_deprecated' } ], + }, + ], + classes: [ + { + name: 'Example', + methods: [ + { name: 'first', hooks: [ { type: 'filter_reference' } ] }, + { name: 'second', hooks: [] }, + ], + }, + ], + hooks: [ { type: 'action' } ], + }, + ]; +} + +test( 'parser inspection counts every supported reference type', () => { + const parsed = records(); + const result = inspectParserRecords( parsed, { + classes: 1, + methods: 2, + functions: 1, + hooks: 2, + filters: 2, + } ); + assert.deepEqual( result, { + records: 1, + counts: { + classes: 1, + methods: 2, + functions: 1, + hooks: 2, + filters: 2, + }, + failures: [], + } ); + assert.equal( parsed[ 0 ].root, '/tmp/docs-preview-source' ); +} ); + +test( 'sanity floors report catastrophic undercounts by symbol type', () => { + const result = inspectParserRecords( records(), { + classes: 2, + methods: 3, + functions: 2, + hooks: 3, + filters: 3, + } ); + assert.equal( result.failures.length, 5 ); + assert.match( result.failures[ 0 ], /1 classes; expected at least 2/ ); +} ); + +test( 'an empty parser array is an advisory validation failure', () => { + const result = inspectParserRecords( [], { + classes: 1, + methods: 1, + functions: 1, + hooks: 1, + filters: 1, + } ); + assert.deepEqual( result.counts, { + classes: 0, + methods: 0, + functions: 0, + hooks: 0, + filters: 0, + } ); + assert.equal( result.failures.length, 6 ); + assert.equal( result.failures[ 0 ], 'Parser produced no file records.' ); +} ); + +test( 'parser inspection rejects excluded bundled extension source', () => { + const parsed = records(); + parsed[ 0 ].path = 'wp-content/plugins/hello.php'; + assert.throws( + () => inspectParserRecords( parsed, {} ), + /contains excluded source/ + ); +} ); + +test( 'generateParserJson stages PHP, invokes the pinned parser, and normalizes output', async () => { + const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-parser-' ) ); + const source = path.join( temporary, 'wordpress/src' ); + await mkdir( path.join( source, 'wp-includes' ), { recursive: true } ); + await writeFile( path.join( source, 'wp-includes/version.php' ), ' { + invocation = { command, args }; + await writeFile( output, JSON.stringify( records() ) ); + }; + const result = await generateParserJson( { + source: path.dirname( source ), + stagedSource: path.join( temporary, 'staged' ), + parser: '/cache/parser', + output, + minimumSymbols: { + classes: 1, + methods: 2, + functions: 1, + hooks: 2, + filters: 2, + }, + runImplementation, + } ); + assert.equal( result.sourceFiles, 2 ); + assert.equal( invocation.command, 'php' ); + assert.equal( invocation.args.at( -1 ), output ); + const normalized = JSON.parse( await readFile( output, 'utf8' ) ); + assert.equal( normalized[ 0 ].root, '/tmp/docs-preview-source' ); +} ); From 173b818807f4e037f7db944f53197f871ca618c7 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 11:38:37 +0400 Subject: [PATCH 06/59] Build/Test Tools: Package Code Reference snapshots The invariant base is not a runnable reference. Restore it, import every parser record, cache source, remove the parser, and only then lock the runtime. An oversized result must never reach publication. --- .../docs-playground-preview/lib/final.mjs | 122 +++++++++++++++++ .../php/complete-import.php | 48 +++++++ .../test/final.test.mjs | 126 ++++++++++++++++++ 3 files changed, 296 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/final.mjs create mode 100644 .github/scripts/docs-playground-preview/php/complete-import.php create mode 100644 .github/scripts/docs-playground-preview/test/final.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/final.mjs b/.github/scripts/docs-playground-preview/lib/final.mjs new file mode 100644 index 0000000000000..53950b94c54ad --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/final.mjs @@ -0,0 +1,122 @@ +import { copyFile, mkdir, rm, stat, writeFile } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +import { sha256File } from './files.mjs'; +import { run } from './process.mjs'; + +const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); +const PHP_ROOT = path.resolve( LIBRARY_ROOT, '../php' ); + +function bundled( resourcePath ) { + return { resource: 'bundled', path: resourcePath }; +} + +export function createFinalBlueprint( inputs ) { + return { + $schema: inputs.dependencies.playground.blueprintSchema, + meta: { + title: 'WordPress Core Code Reference preview', + author: 'WordPress', + description: 'Complete Core Code Reference imported into the cached site.', + }, + preferredVersions: { + php: inputs.dependencies.playground.phpVersion, + wp: inputs.wordpress.version, + }, + landingPage: '/reference/', + login: false, + features: { networking: false }, + extraLibraries: [ 'wp-cli' ], + steps: [ + { + step: 'unzip', + zipFile: bundled( 'base.zip' ), + extractToPath: '/', + }, + { + step: 'writeFile', + path: '/tmp/reference.json', + data: bundled( 'reference.json' ), + }, + { + step: 'wp-cli', + command: 'wp parser import /tmp/reference.json --quick --user=1', + }, + { + step: 'writeFile', + path: '/tmp/docs-preview-complete-import.php', + data: bundled( 'complete-import.php' ), + }, + { + step: 'wp-cli', + command: 'wp eval-file /tmp/docs-preview-complete-import.php', + }, + { + step: 'rmdir', + path: '/wordpress/wp-content/plugins/phpdoc-parser', + }, + { + step: 'defineWpConfigConsts', + method: 'rewrite-wp-config', + consts: { + DISABLE_WP_CRON: true, + AUTOMATIC_UPDATER_DISABLED: true, + WP_AUTO_UPDATE_CORE: false, + DISALLOW_FILE_MODS: true, + }, + }, + ], + }; +} + +export async function packageFinalSnapshot( inputs, options ) { + const runImplementation = options.runImplementation || run; + const work = path.resolve( options.workDirectory ); + const output = path.resolve( options.output ); + await rm( work, { recursive: true, force: true } ); + await mkdir( work, { recursive: true } ); + await mkdir( path.dirname( output ), { recursive: true } ); + await copyFile( path.join( inputs.cacheDirectory, 'base.zip' ), path.join( work, 'base.zip' ) ); + await copyFile( options.referenceJson, path.join( work, 'reference.json' ) ); + await copyFile( + path.join( PHP_ROOT, 'complete-import.php' ), + path.join( work, 'complete-import.php' ) + ); + const blueprint = path.join( work, 'final-blueprint.json' ); + await writeFile( + blueprint, + `${ JSON.stringify( createFinalBlueprint( inputs ), null, 2 ) }\n` + ); + await runImplementation( + options.playgroundCli, + [ + 'build-snapshot', + '--php', + inputs.dependencies.playground.phpVersion, + '--wp', + inputs.wordpress.version, + '--blueprint', + blueprint, + '--blueprint-may-read-adjacent-files', + '--mount', + `${ path.resolve( options.stagedSource ) }:/tmp/docs-preview-source`, + '--outfile', + output, + '--verbosity', + 'normal', + ], + { label: 'build final Code Reference snapshot' } + ); + const snapshot = await stat( output ); + if ( snapshot.size > inputs.dependencies.limits.snapshotBytes ) { + throw new Error( + `Snapshot exceeds 100 MiB: ${ snapshot.size } > ${ inputs.dependencies.limits.snapshotBytes }.` + ); + } + return { + filename: path.basename( output ), + bytes: snapshot.size, + sha256: await sha256File( output ), + }; +} diff --git a/.github/scripts/docs-playground-preview/php/complete-import.php b/.github/scripts/docs-playground-preview/php/complete-import.php new file mode 100644 index 0000000000000..9839af6059f13 --- /dev/null +++ b/.github/scripts/docs-playground-preview/php/complete-import.php @@ -0,0 +1,48 @@ + 'wp-parser-class', + 'methods' => 'wp-parser-method', + 'functions' => 'wp-parser-function', + 'hooks' => 'wp-parser-hook', +); +$counts = array(); +foreach ( $post_types as $name => $post_type ) { + $counts[ $name ] = (int) wp_count_posts( $post_type )->publish; +} + +$marker = array( + 'schemaVersion' => 1, + 'stage' => 'complete-import', + 'counts' => $counts, +); +$written = file_put_contents( + WP_CONTENT_DIR . '/docs-preview-import.json', + wp_json_encode( $marker, JSON_PRETTY_PRINT ) . "\n" +); +if ( false === $written ) { + throw new RuntimeException( 'Unable to record the completed import.' ); +} + +flush_rewrite_rules( false ); diff --git a/.github/scripts/docs-playground-preview/test/final.test.mjs b/.github/scripts/docs-playground-preview/test/final.test.mjs new file mode 100644 index 0000000000000..9e4d43c322b39 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/final.test.mjs @@ -0,0 +1,126 @@ +import assert from 'node:assert/strict'; +import { + mkdir, + mkdtemp, + open, + readFile, + writeFile, +} from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + createFinalBlueprint, + packageFinalSnapshot, +} from '../lib/final.mjs'; + +function inputs( cacheDirectory, snapshotBytes = 1024 ) { + return { + cacheDirectory, + wordpress: { version: '7.2-beta1' }, + dependencies: { + playground: { + blueprintSchema: 'https://playground.wordpress.net/blueprint-schema.json', + phpVersion: '8.4', + }, + limits: { snapshotBytes }, + }, + }; +} + +test( 'the final Blueprint restores the base before the complete import', () => { + const blueprint = createFinalBlueprint( inputs( '/cache' ) ); + assert.equal( blueprint.landingPage, '/reference/' ); + assert.equal( blueprint.login, false ); + assert.deepEqual( blueprint.features, { networking: false } ); + assert.deepEqual( + blueprint.steps.map( ( step ) => step.step ), + [ + 'unzip', + 'writeFile', + 'wp-cli', + 'writeFile', + 'wp-cli', + 'rmdir', + 'defineWpConfigConsts', + ] + ); + assert.equal( blueprint.steps[ 0 ].extractToPath, '/' ); + assert.match( blueprint.steps[ 2 ].command, /parser import.+--quick/ ); + assert.equal( + blueprint.steps.at( -2 ).path, + '/wordpress/wp-content/plugins/phpdoc-parser' + ); + assert.deepEqual( blueprint.steps.at( -1 ), { + step: 'defineWpConfigConsts', + method: 'rewrite-wp-config', + consts: { + DISABLE_WP_CRON: true, + AUTOMATIC_UPDATER_DISABLED: true, + WP_AUTO_UPDATE_CORE: false, + DISALLOW_FILE_MODS: true, + }, + } ); +} ); + +async function fixture( snapshotBytes = 1024 ) { + const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-final-' ) ); + const cache = path.join( root, 'cache' ); + await mkdir( cache ); + await writeFile( path.join( cache, 'base.zip' ), 'base' ); + const referenceJson = path.join( root, 'reference.json' ); + await writeFile( referenceJson, '[]' ); + return { + root, + resolved: inputs( cache, snapshotBytes ), + referenceJson, + output: path.join( root, 'output/snapshot.zip' ), + }; +} + +test( 'final packaging returns publisher metadata for a bounded snapshot', async () => { + const current = await fixture(); + let invocation; + const runImplementation = async ( command, args ) => { + invocation = { command, args }; + await writeFile( current.output, 'snapshot' ); + }; + const snapshot = await packageFinalSnapshot( current.resolved, { + workDirectory: path.join( current.root, 'work' ), + output: current.output, + referenceJson: current.referenceJson, + stagedSource: '/source', + playgroundCli: '/tools/wp-playground-cli', + runImplementation, + } ); + assert.equal( snapshot.filename, 'snapshot.zip' ); + assert.equal( snapshot.bytes, 8 ); + assert.match( snapshot.sha256, /^[0-9a-f]{64}$/ ); + assert.equal( invocation.command, '/tools/wp-playground-cli' ); + assert.equal( invocation.args[ invocation.args.indexOf( '--mount' ) + 1 ], '/source:/tmp/docs-preview-source' ); + const blueprint = JSON.parse( + await readFile( path.join( current.root, 'work/final-blueprint.json' ), 'utf8' ) + ); + assert.equal( blueprint.steps[ 0 ].zipFile.path, 'base.zip' ); +} ); + +test( 'the 100 MiB snapshot boundary always fails closed', async () => { + const current = await fixture( 8 ); + const runImplementation = async () => { + const output = await open( current.output, 'w' ); + await output.truncate( 9 ); + await output.close(); + }; + await assert.rejects( + packageFinalSnapshot( current.resolved, { + workDirectory: path.join( current.root, 'work' ), + output: current.output, + referenceJson: current.referenceJson, + stagedSource: '/source', + playgroundCli: '/tools/wp-playground-cli', + runImplementation, + } ), + /exceeds 100 MiB/ + ); +} ); From 2a8dc89ad4dcf24e64820cb33ebab89a89950f95 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 11:50:55 +0400 Subject: [PATCH 07/59] Build/Test Tools: Add Code Reference runtime policy Runtime policy cannot live only in build metadata. Install it after import, show the exact source and run on every page, and expose the final state for behavioral validation. Block WordPress HTTP requests so the preview cannot quietly depend on the network. --- .../docs-playground-preview/lib/final.mjs | 30 ++++- .../docs-playground-preview/lib/runtime.mjs | 127 ++++++++++++++++++ .../test/final.test.mjs | 49 ++++--- .../test/runtime.test.mjs | 51 +++++++ 4 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/lib/runtime.mjs create mode 100644 .github/scripts/docs-playground-preview/test/runtime.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/final.mjs b/.github/scripts/docs-playground-preview/lib/final.mjs index 53950b94c54ad..059e64ca69132 100644 --- a/.github/scripts/docs-playground-preview/lib/final.mjs +++ b/.github/scripts/docs-playground-preview/lib/final.mjs @@ -4,6 +4,7 @@ import path from 'node:path'; import { sha256File } from './files.mjs'; import { run } from './process.mjs'; +import { renderRuntimePlugin } from './runtime.mjs'; const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); const PHP_ROOT = path.resolve( LIBRARY_ROOT, '../php' ); @@ -18,7 +19,8 @@ export function createFinalBlueprint( inputs ) { meta: { title: 'WordPress Core Code Reference preview', author: 'WordPress', - description: 'Complete Core Code Reference imported into the cached site.', + description: + 'Complete Core Code Reference imported into the cached site.', }, preferredVersions: { php: inputs.dependencies.playground.phpVersion, @@ -41,7 +43,8 @@ export function createFinalBlueprint( inputs ) { }, { step: 'wp-cli', - command: 'wp parser import /tmp/reference.json --quick --user=1', + command: + 'wp parser import /tmp/reference.json --quick --user=1', }, { step: 'writeFile', @@ -56,6 +59,11 @@ export function createFinalBlueprint( inputs ) { step: 'rmdir', path: '/wordpress/wp-content/plugins/phpdoc-parser', }, + { + step: 'writeFile', + path: '/wordpress/wp-content/mu-plugins/001-docs-preview-runtime.php', + data: bundled( 'runtime.php' ), + }, { step: 'defineWpConfigConsts', method: 'rewrite-wp-config', @@ -77,12 +85,22 @@ export async function packageFinalSnapshot( inputs, options ) { await rm( work, { recursive: true, force: true } ); await mkdir( work, { recursive: true } ); await mkdir( path.dirname( output ), { recursive: true } ); - await copyFile( path.join( inputs.cacheDirectory, 'base.zip' ), path.join( work, 'base.zip' ) ); - await copyFile( options.referenceJson, path.join( work, 'reference.json' ) ); + await copyFile( + path.join( inputs.cacheDirectory, 'base.zip' ), + path.join( work, 'base.zip' ) + ); + await copyFile( + options.referenceJson, + path.join( work, 'reference.json' ) + ); await copyFile( path.join( PHP_ROOT, 'complete-import.php' ), path.join( work, 'complete-import.php' ) ); + await writeFile( + path.join( work, 'runtime.php' ), + renderRuntimePlugin( options.provenance ) + ); const blueprint = path.join( work, 'final-blueprint.json' ); await writeFile( blueprint, @@ -100,7 +118,9 @@ export async function packageFinalSnapshot( inputs, options ) { blueprint, '--blueprint-may-read-adjacent-files', '--mount', - `${ path.resolve( options.stagedSource ) }:/tmp/docs-preview-source`, + `${ path.resolve( + options.stagedSource + ) }:/tmp/docs-preview-source`, '--outfile', output, '--verbosity', diff --git a/.github/scripts/docs-playground-preview/lib/runtime.mjs b/.github/scripts/docs-playground-preview/lib/runtime.mjs new file mode 100644 index 0000000000000..a37701e0e3e67 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/runtime.mjs @@ -0,0 +1,127 @@ +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; +const RUN_URL = + /^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/actions\/runs\/\d+$/; + +function phpString( value ) { + return JSON.stringify( value ); +} + +export function validateProvenance( provenance ) { + if ( ! REPOSITORY.test( provenance?.sourceRepository || '' ) ) { + throw new Error( 'Preview provenance repository is invalid.' ); + } + if ( ! FULL_COMMIT.test( provenance.sourceSha || '' ) ) { + throw new Error( 'Preview provenance commit is invalid.' ); + } + if ( + Number.isNaN( Date.parse( provenance.generationTimestamp ) ) || + ! provenance.generationTimestamp.endsWith( 'Z' ) + ) { + throw new Error( 'Preview provenance timestamp must be UTC.' ); + } + if ( + provenance.runUrl !== null && + ! RUN_URL.test( provenance.runUrl || '' ) + ) { + throw new Error( 'Preview provenance run URL is invalid.' ); + } + return provenance; +} + +export function renderRuntimePlugin( candidate ) { + const provenance = validateProvenance( candidate ); + const runUrl = + provenance.runUrl === null ? 'null' : phpString( provenance.runUrl ); + return ` ${ phpString( provenance.sourceRepository ) }, + 'sourceSha' => ${ phpString( provenance.sourceSha ) }, + 'generationTimestamp' => ${ phpString( provenance.generationTimestamp ) }, + 'runUrl' => ${ runUrl }, +); + +add_filter( + 'pre_http_request', + static function() { + return new WP_Error( + 'docs_preview_network_disabled', + 'Outbound networking is disabled in the Code Reference preview.' + ); + }, + PHP_INT_MAX +); + +$wporg_docs_preview_banner_rendered = false; +$wporg_docs_preview_render_banner = static function() use ( &$wporg_docs_preview_banner_rendered, $wporg_docs_preview_provenance ) { + if ( $wporg_docs_preview_banner_rendered || is_admin() ) { + return; + } + $wporg_docs_preview_banner_rendered = true; + $commit_url = sprintf( + 'https://github.com/%s/commit/%s', + $wporg_docs_preview_provenance['sourceRepository'], + $wporg_docs_preview_provenance['sourceSha'] + ); + ?> + + 'GET', + 'permission_callback' => '__return_true', + 'callback' => static function() use ( $wporg_docs_preview_provenance ) { + $marker_file = WP_CONTENT_DIR . '/docs-preview-import.json'; + $marker = file_exists( $marker_file ) + ? json_decode( file_get_contents( $marker_file ), true ) + : null; + $network = wp_remote_get( 'https://api.wordpress.org/' ); + return array( + 'provenance' => $wporg_docs_preview_provenance, + 'import' => $marker, + 'outboundNetworkDisabled' => is_wp_error( $network ) && 'docs_preview_network_disabled' === $network->get_error_code(), + 'constants' => array( + 'DISABLE_WP_CRON' => defined( 'DISABLE_WP_CRON' ) && true === DISABLE_WP_CRON, + 'AUTOMATIC_UPDATER_DISABLED' => defined( 'AUTOMATIC_UPDATER_DISABLED' ) && true === AUTOMATIC_UPDATER_DISABLED, + 'WP_AUTO_UPDATE_CORE' => defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE, + 'DISALLOW_FILE_MODS' => defined( 'DISALLOW_FILE_MODS' ) && true === DISALLOW_FILE_MODS, + ), + ); + }, + ) + ); + } +); +`; +} diff --git a/.github/scripts/docs-playground-preview/test/final.test.mjs b/.github/scripts/docs-playground-preview/test/final.test.mjs index 9e4d43c322b39..f2bc4773dc055 100644 --- a/.github/scripts/docs-playground-preview/test/final.test.mjs +++ b/.github/scripts/docs-playground-preview/test/final.test.mjs @@ -1,19 +1,10 @@ import assert from 'node:assert/strict'; -import { - mkdir, - mkdtemp, - open, - readFile, - writeFile, -} from 'node:fs/promises'; +import { mkdir, mkdtemp, open, readFile, writeFile } from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { test } from 'node:test'; -import { - createFinalBlueprint, - packageFinalSnapshot, -} from '../lib/final.mjs'; +import { createFinalBlueprint, packageFinalSnapshot } from '../lib/final.mjs'; function inputs( cacheDirectory, snapshotBytes = 1024 ) { return { @@ -21,7 +12,8 @@ function inputs( cacheDirectory, snapshotBytes = 1024 ) { wordpress: { version: '7.2-beta1' }, dependencies: { playground: { - blueprintSchema: 'https://playground.wordpress.net/blueprint-schema.json', + blueprintSchema: + 'https://playground.wordpress.net/blueprint-schema.json', phpVersion: '8.4', }, limits: { snapshotBytes }, @@ -43,15 +35,20 @@ test( 'the final Blueprint restores the base before the complete import', () => 'writeFile', 'wp-cli', 'rmdir', + 'writeFile', 'defineWpConfigConsts', ] ); assert.equal( blueprint.steps[ 0 ].extractToPath, '/' ); assert.match( blueprint.steps[ 2 ].command, /parser import.+--quick/ ); assert.equal( - blueprint.steps.at( -2 ).path, + blueprint.steps.at( -3 ).path, '/wordpress/wp-content/plugins/phpdoc-parser' ); + assert.equal( + blueprint.steps.at( -2 ).path, + '/wordpress/wp-content/mu-plugins/001-docs-preview-runtime.php' + ); assert.deepEqual( blueprint.steps.at( -1 ), { step: 'defineWpConfigConsts', method: 'rewrite-wp-config', @@ -65,7 +62,9 @@ test( 'the final Blueprint restores the base before the complete import', () => } ); async function fixture( snapshotBytes = 1024 ) { - const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-final-' ) ); + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-final-' ) + ); const cache = path.join( root, 'cache' ); await mkdir( cache ); await writeFile( path.join( cache, 'base.zip' ), 'base' ); @@ -92,15 +91,27 @@ test( 'final packaging returns publisher metadata for a bounded snapshot', async referenceJson: current.referenceJson, stagedSource: '/source', playgroundCli: '/tools/wp-playground-cli', + provenance: { + sourceRepository: 'example/wordpress-develop', + sourceSha: 'a'.repeat( 40 ), + generationTimestamp: '2026-08-09T12:34:56.000Z', + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', + }, runImplementation, } ); assert.equal( snapshot.filename, 'snapshot.zip' ); assert.equal( snapshot.bytes, 8 ); assert.match( snapshot.sha256, /^[0-9a-f]{64}$/ ); assert.equal( invocation.command, '/tools/wp-playground-cli' ); - assert.equal( invocation.args[ invocation.args.indexOf( '--mount' ) + 1 ], '/source:/tmp/docs-preview-source' ); + assert.equal( + invocation.args[ invocation.args.indexOf( '--mount' ) + 1 ], + '/source:/tmp/docs-preview-source' + ); const blueprint = JSON.parse( - await readFile( path.join( current.root, 'work/final-blueprint.json' ), 'utf8' ) + await readFile( + path.join( current.root, 'work/final-blueprint.json' ), + 'utf8' + ) ); assert.equal( blueprint.steps[ 0 ].zipFile.path, 'base.zip' ); } ); @@ -119,6 +130,12 @@ test( 'the 100 MiB snapshot boundary always fails closed', async () => { referenceJson: current.referenceJson, stagedSource: '/source', playgroundCli: '/tools/wp-playground-cli', + provenance: { + sourceRepository: 'example/wordpress-develop', + sourceSha: 'a'.repeat( 40 ), + generationTimestamp: '2026-08-09T12:34:56.000Z', + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', + }, runImplementation, } ), /exceeds 100 MiB/ diff --git a/.github/scripts/docs-playground-preview/test/runtime.test.mjs b/.github/scripts/docs-playground-preview/test/runtime.test.mjs new file mode 100644 index 0000000000000..9cecb70a94378 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/runtime.test.mjs @@ -0,0 +1,51 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; + +import { renderRuntimePlugin, validateProvenance } from '../lib/runtime.mjs'; + +const provenance = { + sourceRepository: 'example/wordpress-develop', + sourceSha: 'a'.repeat( 40 ), + generationTimestamp: '2026-08-09T12:34:56.000Z', + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', +}; + +test( 'runtime provenance requires exact public build identity', () => { + assert.equal( validateProvenance( provenance ), provenance ); + assert.throws( + () => validateProvenance( { ...provenance, sourceSha: 'trunk' } ), + /commit is invalid/ + ); + assert.throws( + () => + validateProvenance( { + ...provenance, + runUrl: 'https://example.com/', + } ), + /run URL is invalid/ + ); +} ); + +test( 'runtime plugin exposes the banner, health, network, and policy behavior', () => { + const plugin = renderRuntimePlugin( provenance ); + assert.match( plugin, /wporg-code-reference-preview-provenance/ ); + assert.match( plugin, /wp_body_open/ ); + assert.match( plugin, /wp_footer/ ); + assert.match( plugin, /docs-preview\/v1/ ); + assert.match( plugin, /docs_preview_network_disabled/ ); + for ( const name of [ + 'DISABLE_WP_CRON', + 'AUTOMATIC_UPDATER_DISABLED', + 'WP_AUTO_UPDATE_CORE', + 'DISALLOW_FILE_MODS', + ] ) { + assert.match( plugin, new RegExp( name ) ); + } + assert.match( plugin, new RegExp( provenance.sourceSha ) ); + assert.match( plugin, new RegExp( provenance.runUrl ) ); +} ); + +test( 'local runtime provenance may omit an Actions run', () => { + const plugin = renderRuntimePlugin( { ...provenance, runUrl: null } ); + assert.match( plugin, /'runUrl'\s+=> null/ ); +} ); From ca620187e7c065554984c591d853064117115081 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 12:10:33 +0400 Subject: [PATCH 08/59] Build/Test Tools: Validate Code Reference snapshots Parser success does not prove a runnable preview. Boot the exported snapshot and exercise the index, representative symbols, search, provenance, import completion, and runtime policy through Playground. Return defects as validation state so advisory mode can report them without publishing the candidate. --- .../docs-playground-preview/lib/validate.mjs | 308 ++++++++++++++++++ .../test/validate.test.mjs | 203 ++++++++++++ 2 files changed, 511 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/validate.mjs create mode 100644 .github/scripts/docs-playground-preview/test/validate.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs new file mode 100644 index 0000000000000..d9346326b17d0 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -0,0 +1,308 @@ +import { spawn } from 'node:child_process'; +import { copyFile, mkdir, rm, writeFile } from 'node:fs/promises'; +import { createServer } from 'node:net'; +import path from 'node:path'; + +const BANNER_ID = 'wporg-code-reference-preview-provenance'; + +function bundled( resourcePath ) { + return { resource: 'bundled', path: resourcePath }; +} + +export function createValidationBlueprint( inputs ) { + return { + $schema: inputs.dependencies.playground.blueprintSchema, + preferredVersions: { + php: inputs.dependencies.playground.phpVersion, + wp: inputs.wordpress.version, + }, + landingPage: '/reference/', + login: false, + features: { networking: false }, + steps: [ + { + step: 'unzip', + zipFile: bundled( 'snapshot.zip' ), + extractToPath: '/', + }, + ], + }; +} + +function delay( milliseconds ) { + return new Promise( ( resolve ) => setTimeout( resolve, milliseconds ) ); +} + +async function availablePort() { + const server = createServer(); + await new Promise( ( resolve, reject ) => { + server.once( 'error', reject ); + server.listen( 0, '127.0.0.1', resolve ); + } ); + const port = server.address().port; + await new Promise( ( resolve ) => server.close( resolve ) ); + return port; +} + +function startServer( command, args ) { + const child = spawn( command, args, { + stdio: [ 'ignore', 'pipe', 'pipe' ], + } ); + let output = ''; + child.stdout.on( 'data', ( chunk ) => { + output += chunk; + } ); + child.stderr.on( 'data', ( chunk ) => { + output += chunk; + } ); + const closed = new Promise( ( resolve ) => { + child.once( 'error', ( error ) => resolve( { error } ) ); + child.once( 'close', ( code, signal ) => resolve( { code, signal } ) ); + } ); + return { child, closed, output: () => output }; +} + +async function stopServer( server ) { + if ( server.child.exitCode !== null || server.child.signalCode !== null ) { + return; + } + server.child.kill( 'SIGTERM' ); + const stopped = await Promise.race( [ + server.closed.then( () => true ), + delay( 5000 ).then( () => false ), + ] ); + if ( ! stopped ) { + server.child.kill( 'SIGKILL' ); + await server.closed; + } +} + +async function waitForBoot( baseUrl, server, fetchImplementation ) { + const deadline = Date.now() + 120000; + while ( Date.now() < deadline ) { + const state = await Promise.race( [ + server.closed, + delay( 250 ).then( () => null ), + ] ); + if ( state ) { + throw new Error( + `Playground exited before boot (${ + state.code ?? state.signal ?? state.error?.message + }).\n${ server.output() }` + ); + } + try { + const response = await fetchImplementation( + `${ baseUrl }/wp-json/docs-preview/v1/health` + ); + if ( response.ok ) { + return; + } + } catch { + // The server is not accepting requests yet. + } + } + throw new Error( + `Playground did not boot within 120 seconds.\n${ server.output() }` + ); +} + +async function withPlaygroundServer( inputs, options, inspect ) { + const work = path.resolve( options.workDirectory ); + await rm( work, { recursive: true, force: true } ); + await mkdir( work, { recursive: true } ); + await copyFile( options.snapshot, path.join( work, 'snapshot.zip' ) ); + const blueprint = path.join( work, 'validation-blueprint.json' ); + await writeFile( + blueprint, + `${ JSON.stringify( createValidationBlueprint( inputs ), null, 2 ) }\n` + ); + const port = await availablePort(); + const baseUrl = `http://127.0.0.1:${ port }`; + const server = startServer( options.playgroundCli, [ + 'server', + '--php', + inputs.dependencies.playground.phpVersion, + '--wp', + inputs.wordpress.version, + '--blueprint', + blueprint, + '--blueprint-may-read-adjacent-files', + '--site-url', + baseUrl, + '--port', + String( port ), + '--workers', + '1', + '--verbosity', + 'normal', + ] ); + try { + await waitForBoot( baseUrl, server, options.fetchImplementation ); + return await inspect( baseUrl ); + } finally { + await stopServer( server ); + await rm( work, { recursive: true, force: true } ); + } +} + +function provenanceFailure( actual, expected ) { + for ( const name of [ + 'sourceRepository', + 'sourceSha', + 'generationTimestamp', + 'runUrl', + ] ) { + if ( actual?.[ name ] !== expected[ name ] ) { + return `Health provenance ${ name } does not match the build.`; + } + } + return null; +} + +function checkBanner( name, body, provenance, failures ) { + const timestamp = provenance.generationTimestamp + .slice( 0, 19 ) + .replace( 'T', ' ' ); + const expected = [ + `id="${ BANNER_ID }"`, + provenance.sourceRepository, + provenance.sourceSha, + `${ timestamp } UTC`, + ]; + if ( provenance.runUrl ) { + expected.push( provenance.runUrl ); + } + for ( const value of expected ) { + if ( ! body.includes( value ) ) { + failures.push( + `${ name } route has incomplete provenance banner.` + ); + } + } +} + +export async function inspectSnapshotBehavior( inputs, options ) { + const failures = []; + const checks = {}; + const request = async ( route ) => { + const response = await options.fetchImplementation( + `${ options.baseUrl }${ route }` + ); + return { + status: response.status, + url: response.url, + body: await response.text(), + }; + }; + + let health; + try { + const response = await request( '/wp-json/docs-preview/v1/health' ); + checks.health = response.status; + health = JSON.parse( response.body ); + if ( response.status !== 200 ) { + failures.push( `Health route returned HTTP ${ response.status }.` ); + } + } catch ( error ) { + failures.push( `Health route failed: ${ error.message }` ); + } + if ( health ) { + const mismatch = provenanceFailure( + health.provenance, + options.provenance + ); + if ( mismatch ) { + failures.push( mismatch ); + } + if ( health.import?.stage !== 'complete-import' ) { + failures.push( 'Complete import terminal stage is missing.' ); + } + if ( health.outboundNetworkDisabled !== true ) { + failures.push( 'WordPress outbound networking is not disabled.' ); + } + for ( const name of [ + 'DISABLE_WP_CRON', + 'AUTOMATIC_UPDATER_DISABLED', + 'WP_AUTO_UPDATE_CORE', + 'DISALLOW_FILE_MODS', + ] ) { + if ( health.constants?.[ name ] !== true ) { + failures.push( + `Runtime policy constant ${ name } is not enforced.` + ); + } + } + } + + for ( const [ name, route ] of Object.entries( + inputs.dependencies.validation.routes + ) ) { + try { + const response = await request( route ); + checks[ name ] = response.status; + if ( response.status !== 200 ) { + failures.push( + `${ name } route returned HTTP ${ response.status }.` + ); + } + const requested = new URL( route, options.baseUrl ); + if ( + ! response.url || + new URL( response.url ).pathname !== requested.pathname + ) { + failures.push( + `${ name } route redirected away from its stable path.` + ); + } + checkBanner( name, response.body, options.provenance, failures ); + } catch ( error ) { + failures.push( `${ name } route failed: ${ error.message }` ); + } + } + + try { + const search = inputs.dependencies.validation.search; + const response = await request( search.path ); + checks.search = response.status; + if ( + response.status !== 200 || + ! response.body.includes( search.expectedText ) + ) { + failures.push( + 'Local Code Reference search did not return the expected result.' + ); + } + checkBanner( 'search', response.body, options.provenance, failures ); + } catch ( error ) { + failures.push( + `Local Code Reference search failed: ${ error.message }` + ); + } + + if ( options.requireRunUrl && ! options.provenance.runUrl ) { + failures.push( 'Published previews require an Actions run URL.' ); + } + return { failures, checks }; +} + +export async function validateSnapshot( inputs, options ) { + const fetchImplementation = options.fetchImplementation || globalThis.fetch; + try { + return await ( options.serveImplementation || withPlaygroundServer )( + inputs, + { ...options, fetchImplementation }, + ( baseUrl ) => + inspectSnapshotBehavior( inputs, { + ...options, + baseUrl, + fetchImplementation, + } ) + ); + } catch ( error ) { + return { + failures: [ `Playground boot failed: ${ error.message }` ], + checks: {}, + }; + } +} diff --git a/.github/scripts/docs-playground-preview/test/validate.test.mjs b/.github/scripts/docs-playground-preview/test/validate.test.mjs new file mode 100644 index 0000000000000..2233c8a547f61 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/validate.test.mjs @@ -0,0 +1,203 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; + +import { + createValidationBlueprint, + inspectSnapshotBehavior, + validateSnapshot, +} from '../lib/validate.mjs'; + +const provenance = { + sourceRepository: 'example/wordpress-develop', + sourceSha: 'a'.repeat( 40 ), + generationTimestamp: '2026-08-09T12:34:56.000Z', + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', +}; + +function inputs() { + return { + wordpress: { version: '7.2-beta1' }, + dependencies: { + playground: { + blueprintSchema: + 'https://playground.wordpress.net/blueprint-schema.json', + phpVersion: '8.4', + }, + validation: { + routes: { + index: '/reference/', + class: '/reference/classes/example/', + method: '/reference/classes/example/run/', + function: '/reference/functions/example/', + hook: '/reference/hooks/example_action/', + filter: '/reference/hooks/example_filter/', + }, + search: { path: '/?s=example', expectedText: 'example_result' }, + }, + }, + }; +} + +function response( body, status = 200, url = 'http://127.0.0.1:9400/' ) { + return { + status, + url, + text: async () => + typeof body === 'string' ? body : JSON.stringify( body ), + }; +} + +function healthyFetch( url ) { + if ( url.endsWith( '/wp-json/docs-preview/v1/health' ) ) { + return response( + { + provenance, + import: { stage: 'complete-import' }, + outboundNetworkDisabled: true, + constants: { + DISABLE_WP_CRON: true, + AUTOMATIC_UPDATER_DISABLED: true, + WP_AUTO_UPDATE_CORE: true, + DISALLOW_FILE_MODS: true, + }, + }, + 200, + url + ); + } + if ( url.includes( '?s=example' ) ) { + return response( + ` example_result`, + 200, + url + ); + } + return response( + ``, + 200, + url + ); +} + +test( 'validation Blueprint boots the exact snapshot without login or networking', () => { + const blueprint = createValidationBlueprint( inputs() ); + assert.equal( blueprint.login, false ); + assert.deepEqual( blueprint.features, { networking: false } ); + assert.equal( blueprint.preferredVersions.php, '8.4' ); + assert.equal( blueprint.preferredVersions.wp, '7.2-beta1' ); + assert.deepEqual( blueprint.steps, [ + { + step: 'unzip', + zipFile: { resource: 'bundled', path: 'snapshot.zip' }, + extractToPath: '/', + }, + ] ); +} ); + +test( 'behavioral validation covers health, routes, search, and banner', async () => { + const result = await inspectSnapshotBehavior( inputs(), { + baseUrl: 'http://127.0.0.1:9400', + fetchImplementation: healthyFetch, + provenance, + requireRunUrl: true, + } ); + assert.deepEqual( result.failures, [] ); + assert.deepEqual( result.checks, { + health: 200, + index: 200, + class: 200, + method: 200, + function: 200, + hook: 200, + filter: 200, + search: 200, + } ); +} ); + +test( 'behavioral defects are advisory validation failures', async () => { + const result = await inspectSnapshotBehavior( inputs(), { + baseUrl: 'http://127.0.0.1:9400', + fetchImplementation: async ( url ) => { + if ( url.endsWith( '/health' ) ) { + return response( + { + provenance: { + ...provenance, + sourceSha: 'b'.repeat( 40 ), + }, + import: null, + outboundNetworkDisabled: false, + constants: {}, + }, + 200, + url + ); + } + return response( 'broken', 404, url ); + }, + provenance: { ...provenance, runUrl: null }, + requireRunUrl: true, + } ); + assert.ok( + result.failures.some( ( failure ) => failure.includes( 'sourceSha' ) ) + ); + assert.ok( + result.failures.some( ( failure ) => + failure.includes( 'terminal stage' ) + ) + ); + assert.ok( + result.failures.some( ( failure ) => + failure.includes( 'outbound networking' ) + ) + ); + assert.ok( + result.failures.some( ( failure ) => + failure.includes( 'DISABLE_WP_CRON' ) + ) + ); + assert.ok( + result.failures.some( ( failure ) => failure.includes( 'class route' ) ) + ); + assert.ok( + result.failures.some( ( failure ) => failure.includes( 'search' ) ) + ); + assert.ok( + result.failures.some( ( failure ) => + failure.includes( 'Actions run URL' ) + ) + ); +} ); + +test( 'symbol routes may not redirect to a generic successful page', async () => { + const baseUrl = 'http://127.0.0.1:9400'; + const result = await inspectSnapshotBehavior( inputs(), { + baseUrl, + fetchImplementation: async ( url ) => { + const current = await healthyFetch( url ); + if ( url.includes( '/reference/classes/example/' ) ) { + return { ...current, url: `${ baseUrl }/reference/` }; + } + return current; + }, + provenance, + requireRunUrl: true, + } ); + assert.ok( + result.failures.includes( + 'class route redirected away from its stable path.' + ) + ); +} ); + +test( 'a Playground boot failure is returned as validation state', async () => { + const result = await validateSnapshot( inputs(), { + serveImplementation: async () => { + throw new Error( 'did not boot' ); + }, + } ); + assert.deepEqual( result, { + failures: [ 'Playground boot failed: did not boot' ], + checks: {}, + } ); +} ); From dea4904cef7983a7fe7c64888fae176fb89fc4e6 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 12:33:49 +0400 Subject: [PATCH 09/59] Build/Test Tools: Orchestrate Code Reference previews Workflow YAML must not own build semantics. Resolve the pinned inputs, build or reuse the exact base, parse Core, package once, boot the result, and emit one terminal handoff from a repository-local command. A behavioral failure is never publishable; a fatal build still reports identity and still fails. --- .github/docs-playground-preview/package.json | 1 + .../scripts/docs-playground-preview/build.mjs | 443 ++++++++++++++++++ .../test/build.test.mjs | 292 ++++++++++++ 3 files changed, 736 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/build.mjs create mode 100644 .github/scripts/docs-playground-preview/test/build.test.mjs diff --git a/.github/docs-playground-preview/package.json b/.github/docs-playground-preview/package.json index 0a94f575c3772..63bccaa4d95c8 100644 --- a/.github/docs-playground-preview/package.json +++ b/.github/docs-playground-preview/package.json @@ -8,6 +8,7 @@ "node": "20.20.2" }, "scripts": { + "build": "node ../scripts/docs-playground-preview/build.mjs", "test": "node --test ../scripts/docs-playground-preview/test/*.test.mjs" }, "dependencies": { diff --git a/.github/scripts/docs-playground-preview/build.mjs b/.github/scripts/docs-playground-preview/build.mjs new file mode 100644 index 0000000000000..a28bc9df241ad --- /dev/null +++ b/.github/scripts/docs-playground-preview/build.mjs @@ -0,0 +1,443 @@ +#!/usr/bin/env node + +import { mkdir, writeFile } from 'node:fs/promises'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import path from 'node:path'; + +import { ensureInvariantBase } from './lib/base.mjs'; +import { packageFinalSnapshot } from './lib/final.mjs'; +import { + readResolvedInputs, + resolveBuildInputs, + writeResolvedInputs, +} from './lib/inputs.mjs'; +import { generateParserJson } from './lib/parser.mjs'; +import { run } from './lib/process.mjs'; +import { validateSnapshot } from './lib/validate.mjs'; + +const SCRIPT_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); +const REPOSITORY_ROOT = path.resolve( SCRIPT_ROOT, '../../..' ); +const TOOLING_ROOT = path.join( + REPOSITORY_ROOT, + '.github/docs-playground-preview' +); +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; + +function argumentValue( args, index, name ) { + const value = args[ index + 1 ]; + if ( ! value || value.startsWith( '--' ) ) { + throw new Error( `${ name } requires a value.` ); + } + return value; +} + +export function parseArguments( args, environment = process.env ) { + const values = {}; + for ( let index = 0; index < args.length; index++ ) { + const name = args[ index ]; + if ( name === '--resolve-only' ) { + values.resolveOnly = true; + continue; + } + if ( ! name.startsWith( '--' ) ) { + throw new Error( `Unexpected argument ${ name }.` ); + } + const key = name + .slice( 2 ) + .replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() ); + if ( + ! [ + 'source', + 'sourceRepository', + 'sourceSha', + 'pullRequest', + 'runId', + 'runAttempt', + 'runUrl', + 'runnerImage', + 'cacheRoot', + 'workRoot', + 'output', + 'metadata', + 'inputsOutput', + 'resolvedInputs', + ].includes( key ) + ) { + throw new Error( `Unknown option ${ name }.` ); + } + values[ key ] = argumentValue( args, index, name ); + index++; + } + return { + ...values, + enforce: environment.DOCS_PREVIEW_ENFORCE === 'true', + }; +} + +function positiveInteger( value, label, nullable = true ) { + if ( + ( value === undefined || value === null || value === '' ) && + nullable + ) { + return null; + } + const number = Number( value ); + if ( ! Number.isSafeInteger( number ) || number < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } + return number; +} + +function githubRepository( remote ) { + const match = remote + .trim() + .match( + /^(?:git@github\.com:|https:\/\/github\.com\/)([^/]+\/[^/]+?)(?:\.git)?$/ + ); + return match?.[ 1 ] || null; +} + +async function gitIdentity( source, runImplementation ) { + const sha = await runImplementation( 'git', [ 'rev-parse', 'HEAD' ], { + cwd: source, + capture: true, + quiet: true, + label: 'read source commit', + } ); + const remote = await runImplementation( + 'git', + [ 'config', '--get', 'remote.origin.url' ], + { + cwd: source, + capture: true, + quiet: true, + label: 'read source repository', + } + ); + return { + sha: sha.stdout.trim(), + repository: githubRepository( remote.stdout ), + }; +} + +async function normalizeOptions( raw, implementations ) { + const workspace = path.join( + REPOSITORY_ROOT, + '.cache/docs-playground-preview' + ); + const source = path.resolve( raw.source || REPOSITORY_ROOT ); + let sourceSha = raw.sourceSha; + let sourceRepository = raw.sourceRepository; + if ( ! sourceSha || ! sourceRepository ) { + const inferred = await gitIdentity( source, implementations.run ); + sourceSha ||= inferred.sha; + sourceRepository ||= inferred.repository; + } + if ( ! FULL_COMMIT.test( sourceSha || '' ) ) { + throw new Error( 'sourceSha must be a full lowercase commit hash.' ); + } + if ( ! REPOSITORY.test( sourceRepository || '' ) ) { + throw new Error( + 'sourceRepository must be a GitHub owner/repository.' + ); + } + const workRoot = path.resolve( + raw.workRoot || path.join( workspace, 'work' ) + ); + const outputRoot = path.join( workspace, 'output' ); + return { + ...raw, + source, + sourceSha, + sourceRepository, + pullRequestNumber: positiveInteger( raw.pullRequest, 'pullRequest' ), + workflowRunId: raw.runId || null, + workflowRunAttempt: positiveInteger( raw.runAttempt, 'runAttempt' ), + runUrl: raw.runUrl || null, + runnerImage: + raw.runnerImage || `${ process.platform }-${ process.arch }`, + cacheRoot: path.resolve( + raw.cacheRoot || path.join( workspace, 'cache' ) + ), + workRoot, + output: path.resolve( + raw.output || + path.join( outputRoot, `code-reference-${ sourceSha }.zip` ) + ), + metadata: path.resolve( + raw.metadata || path.join( outputRoot, 'build.json' ) + ), + inputsOutput: path.resolve( + raw.inputsOutput || path.join( workRoot, 'resolved-inputs.json' ) + ), + }; +} + +async function ensureNodeTools( implementations ) { + const playgroundCli = path.join( + TOOLING_ROOT, + `node_modules/.bin/wp-playground-cli${ + process.platform === 'win32' ? '.cmd' : '' + }` + ); + await implementations.run( + 'npm', + [ 'ci', '--ignore-scripts', '--no-audit', '--no-fund' ], + { cwd: TOOLING_ROOT, label: 'install pinned preview tools' } + ); + return playgroundCli; +} + +export async function verifyToolchain( inputs, options = {} ) { + const runImplementation = options.runImplementation || run; + const expected = inputs.dependencies.toolchain; + const nodeVersion = options.nodeVersion || process.versions.node; + if ( nodeVersion !== expected.nodeVersion ) { + throw new Error( + `Node ${ expected.nodeVersion } is required; found ${ nodeVersion }.` + ); + } + const npm = await runImplementation( 'npm', [ '--version' ], { + capture: true, + quiet: true, + label: 'read npm version', + } ); + if ( npm.stdout.trim() !== expected.npmVersion ) { + throw new Error( + `npm ${ + expected.npmVersion + } is required; found ${ npm.stdout.trim() }.` + ); + } + const php = await runImplementation( + 'php', + [ '-r', 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;' ], + { + capture: true, + quiet: true, + label: 'read PHP version', + } + ); + if ( php.stdout.trim() !== inputs.dependencies.playground.phpVersion ) { + throw new Error( + `PHP ${ + inputs.dependencies.playground.phpVersion + } is required; found ${ php.stdout.trim() }.` + ); + } +} + +export function createBuildMetadata( + options, + inputs, + base, + parser, + snapshot, + validation, + generationTimestamp +) { + const validationFailures = [ ...parser.failures, ...validation.failures ]; + return { + schemaVersion: 1, + sourceRepository: options.sourceRepository, + pullRequestNumber: options.pullRequestNumber, + sourceSha: options.sourceSha, + workflowRunId: options.workflowRunId, + workflowRunAttempt: options.workflowRunAttempt, + runUrl: options.runUrl, + resolvedWordPressBeta: inputs.wordpress, + phpVersion: inputs.dependencies.playground.phpVersion, + dependencyManifestDigest: inputs.cacheInputs.dependencyDigest, + snapshotFilename: snapshot.filename, + snapshotBytes: snapshot.bytes, + snapshotSha256: snapshot.sha256, + buildStatus: 'success', + validationStatus: validationFailures.length === 0 ? 'passed' : 'failed', + validationFailures, + parser: { + sourceFiles: parser.sourceFiles, + records: parser.records, + counts: parser.counts, + }, + behavior: { checks: validation.checks }, + cache: { key: inputs.cacheKey, hit: base.cacheHit }, + generationTimestamp, + }; +} + +export function createFailureMetadata( + options, + inputs, + error, + generationTimestamp +) { + return { + schemaVersion: 1, + sourceRepository: options.sourceRepository, + pullRequestNumber: options.pullRequestNumber, + sourceSha: options.sourceSha, + workflowRunId: options.workflowRunId, + workflowRunAttempt: options.workflowRunAttempt, + runUrl: options.runUrl, + resolvedWordPressBeta: inputs?.wordpress || null, + phpVersion: inputs?.dependencies?.playground?.phpVersion || null, + dependencyManifestDigest: inputs?.cacheInputs?.dependencyDigest || null, + snapshotFilename: null, + snapshotBytes: null, + snapshotSha256: null, + buildStatus: 'failed', + validationStatus: 'not-run', + validationFailures: [], + generationTimestamp, + buildError: error.message, + }; +} + +async function writeJson( filename, value ) { + await mkdir( path.dirname( filename ), { recursive: true } ); + await writeFile( filename, `${ JSON.stringify( value, null, 2 ) }\n` ); +} + +const DEFAULT_IMPLEMENTATIONS = { + run, + resolveBuildInputs, + readResolvedInputs, + writeResolvedInputs, + ensureInvariantBase, + generateParserJson, + packageFinalSnapshot, + validateSnapshot, + verifyToolchain, +}; + +export async function buildCodeReferencePreview( rawOptions, overrides = {} ) { + const implementations = { ...DEFAULT_IMPLEMENTATIONS, ...overrides }; + const options = await normalizeOptions( rawOptions, implementations ); + let generationTimestamp; + let inputs; + let result; + try { + inputs = options.resolvedInputs + ? await implementations.readResolvedInputs( options.resolvedInputs ) + : await implementations.resolveBuildInputs( { + repositoryRoot: REPOSITORY_ROOT, + cacheRoot: options.cacheRoot, + platform: process.platform, + architecture: process.arch, + runnerImage: options.runnerImage, + } ); + await implementations.verifyToolchain( inputs, { + runImplementation: implementations.run, + } ); + if ( options.resolveOnly ) { + await implementations.writeResolvedInputs( + inputs, + options.inputsOutput + ); + return { inputs, options }; + } + + generationTimestamp = new Date().toISOString(); + const provenance = { + sourceRepository: options.sourceRepository, + sourceSha: options.sourceSha, + generationTimestamp, + runUrl: options.runUrl, + }; + const playgroundCli = await ensureNodeTools( implementations ); + const base = await implementations.ensureInvariantBase( inputs, { + playgroundCli, + } ); + const parser = await implementations.generateParserJson( { + source: options.source, + stagedSource: path.join( options.workRoot, 'source' ), + parser: path.join( inputs.cacheDirectory, 'parser' ), + output: path.join( options.workRoot, 'reference.json' ), + logFile: path.join( options.workRoot, 'parser.log' ), + minimumSymbols: inputs.dependencies.validation.minimumSymbols, + } ); + const snapshot = await implementations.packageFinalSnapshot( inputs, { + workDirectory: path.join( options.workRoot, 'final' ), + output: options.output, + referenceJson: path.join( options.workRoot, 'reference.json' ), + stagedSource: path.join( options.workRoot, 'source' ), + playgroundCli, + provenance, + } ); + const validation = await implementations.validateSnapshot( inputs, { + snapshot: options.output, + workDirectory: path.join( options.workRoot, 'validation' ), + playgroundCli, + provenance, + requireRunUrl: options.workflowRunId !== null, + } ); + const metadata = createBuildMetadata( + options, + inputs, + base, + parser, + snapshot, + validation, + generationTimestamp + ); + await writeJson( options.metadata, metadata ); + result = { + inputs, + base, + parser, + snapshot, + validation, + metadata, + options, + }; + } catch ( error ) { + try { + await writeJson( + options.metadata, + createFailureMetadata( + options, + inputs, + error, + generationTimestamp || new Date().toISOString() + ) + ); + } catch { + // Preserve the build error when its terminal metadata cannot be written. + } + throw error; + } + const { metadata } = result; + if ( metadata.validationStatus === 'failed' && options.enforce ) { + throw new Error( metadata.validationFailures.join( '\n' ) ); + } + return result; +} + +async function main() { + const result = await buildCodeReferencePreview( + parseArguments( process.argv.slice( 2 ) ) + ); + for ( const failure of result.metadata?.validationFailures || [] ) { + process.stderr.write( `::warning::${ failure }\n` ); + } + process.stdout.write( + `${ JSON.stringify( + result.metadata || { + cacheKey: result.inputs.cacheKey, + resolvedWordPressBeta: result.inputs.wordpress, + }, + null, + 2 + ) }\n` + ); +} + +if ( + import.meta.url === pathToFileURL( path.resolve( process.argv[ 1 ] ) ).href +) { + main().catch( ( error ) => { + process.stderr.write( `${ error.message }\n` ); + process.exitCode = 1; + } ); +} diff --git a/.github/scripts/docs-playground-preview/test/build.test.mjs b/.github/scripts/docs-playground-preview/test/build.test.mjs new file mode 100644 index 0000000000000..2bf0a30bb36fe --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/build.test.mjs @@ -0,0 +1,292 @@ +import assert from 'node:assert/strict'; +import { mkdtemp, readFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + buildCodeReferencePreview, + createBuildMetadata, + createFailureMetadata, + parseArguments, + verifyToolchain, +} from '../build.mjs'; + +const SHA = 'a'.repeat( 40 ); + +function resolved( cacheDirectory ) { + return { + schemaVersion: 1, + cacheKey: 'docs-preview-base-v1-test', + cacheDirectory, + cacheInputs: { dependencyDigest: 'b'.repeat( 64 ) }, + dependencies: { + toolchain: { nodeVersion: '20.20.2', npmVersion: '10.8.2' }, + playground: { phpVersion: '8.4' }, + validation: { + minimumSymbols: { + classes: 1, + methods: 1, + functions: 1, + hooks: 1, + filters: 1, + }, + }, + }, + wordpress: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + }; +} + +function parser( failures = [] ) { + return { + sourceFiles: 2, + records: 1, + counts: { classes: 1, methods: 1, functions: 1, hooks: 1, filters: 1 }, + failures, + }; +} + +test( 'arguments recognize enforcement only at the exact true value', () => { + assert.equal( + parseArguments( [], { DOCS_PREVIEW_ENFORCE: 'true' } ).enforce, + true + ); + assert.equal( + parseArguments( [], { DOCS_PREVIEW_ENFORCE: 'TRUE' } ).enforce, + false + ); + assert.throws( + () => parseArguments( [ '--unknown', 'value' ] ), + /Unknown option/ + ); +} ); + +test( 'the cache cannot claim a toolchain version that did not run', async () => { + const commands = []; + await verifyToolchain( resolved( '/cache' ), { + nodeVersion: '20.20.2', + runImplementation: async ( command ) => { + commands.push( command ); + return { stdout: command === 'npm' ? '10.8.2\n' : '8.4' }; + }, + } ); + assert.deepEqual( commands, [ 'npm', 'php' ] ); + await assert.rejects( + verifyToolchain( resolved( '/cache' ), { + nodeVersion: '22.23.2', + } ), + /Node 20\.20\.2 is required/ + ); +} ); + +test( 'build metadata contains the complete publisher handoff identity', () => { + const metadata = createBuildMetadata( + { + sourceRepository: 'example/wordpress-develop', + pullRequestNumber: 12, + sourceSha: SHA, + workflowRunId: '123', + workflowRunAttempt: 2, + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', + }, + resolved( '/cache' ), + { cacheHit: true }, + parser(), + { filename: 'snapshot.zip', bytes: 42, sha256: 'c'.repeat( 64 ) }, + { failures: [], checks: { index: 200 } }, + '2026-08-09T12:34:56.000Z' + ); + assert.equal( metadata.schemaVersion, 1 ); + assert.equal( metadata.sourceSha, SHA ); + assert.equal( metadata.resolvedWordPressBeta.version, '7.2-beta1' ); + assert.equal( metadata.phpVersion, '8.4' ); + assert.equal( metadata.dependencyManifestDigest, 'b'.repeat( 64 ) ); + assert.equal( metadata.snapshotFilename, 'snapshot.zip' ); + assert.equal( metadata.snapshotBytes, 42 ); + assert.equal( metadata.snapshotSha256, 'c'.repeat( 64 ) ); + assert.equal( metadata.buildStatus, 'success' ); + assert.equal( metadata.validationStatus, 'passed' ); + assert.deepEqual( metadata.behavior.checks, { index: 200 } ); + assert.equal( metadata.generationTimestamp, '2026-08-09T12:34:56.000Z' ); +} ); + +test( 'failed build metadata retains the available trusted handoff identity', () => { + const metadata = createFailureMetadata( + { + sourceRepository: 'example/wordpress-develop', + pullRequestNumber: 12, + sourceSha: SHA, + workflowRunId: '123', + workflowRunAttempt: 2, + runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', + }, + resolved( '/cache' ), + new Error( 'import broke' ), + '2026-08-09T12:34:56.000Z' + ); + assert.equal( metadata.buildStatus, 'failed' ); + assert.equal( metadata.validationStatus, 'not-run' ); + assert.equal( metadata.sourceSha, SHA ); + assert.equal( metadata.resolvedWordPressBeta.version, '7.2-beta1' ); + assert.equal( metadata.snapshotFilename, null ); + assert.equal( metadata.buildError, 'import broke' ); +} ); + +test( 'resolve-only records the exact cache inputs without building', async () => { + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-resolve-' ) + ); + const expected = resolved( path.join( root, 'cache/exact' ) ); + let written; + const result = await buildCodeReferencePreview( + { + source: process.cwd(), + sourceRepository: 'example/wordpress-develop', + sourceSha: SHA, + cacheRoot: path.join( root, 'cache' ), + workRoot: path.join( root, 'work' ), + resolveOnly: true, + }, + { + resolveBuildInputs: async () => expected, + verifyToolchain: async () => {}, + writeResolvedInputs: async ( inputs, filename ) => { + written = { inputs, filename }; + }, + } + ); + assert.equal( result.inputs, expected ); + assert.equal( written.inputs, expected ); + assert.equal( + written.filename, + path.join( root, 'work/resolved-inputs.json' ) + ); +} ); + +async function fixture( failures = [], enforce = false ) { + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-build-' ) + ); + const cache = path.join( root, 'cache/exact' ); + const calls = []; + const overrides = { + run: async () => {}, + verifyToolchain: async () => {}, + readResolvedInputs: async () => resolved( cache ), + ensureInvariantBase: async () => { + calls.push( 'base' ); + return { cacheHit: true }; + }, + generateParserJson: async ( options ) => { + calls.push( 'parser' ); + assert.equal( options.parser, path.join( cache, 'parser' ) ); + return parser( failures ); + }, + packageFinalSnapshot: async () => { + calls.push( 'package' ); + return { + filename: 'snapshot.zip', + bytes: 42, + sha256: 'c'.repeat( 64 ), + }; + }, + validateSnapshot: async () => { + calls.push( 'validate' ); + return { failures: [], checks: { index: 200 } }; + }, + }; + const options = { + source: process.cwd(), + sourceRepository: 'example/wordpress-develop', + sourceSha: SHA, + resolvedInputs: path.join( root, 'inputs.json' ), + workRoot: path.join( root, 'work' ), + output: path.join( root, 'snapshot.zip' ), + metadata: path.join( root, 'build.json' ), + enforce, + }; + return { root, calls, overrides, options }; +} + +test( 'one command builds the base, parser data, package, and handoff in order', async () => { + const current = await fixture(); + const result = await buildCodeReferencePreview( + current.options, + current.overrides + ); + assert.deepEqual( current.calls, [ + 'base', + 'parser', + 'package', + 'validate', + ] ); + assert.equal( result.metadata.validationStatus, 'passed' ); + const written = JSON.parse( + await readFile( path.join( current.root, 'build.json' ), 'utf8' ) + ); + assert.equal( written.snapshotSha256, 'c'.repeat( 64 ) ); +} ); + +test( 'fatal packaging writes failed terminal metadata and still rejects', async () => { + const current = await fixture(); + current.overrides.packageFinalSnapshot = async () => { + throw new Error( 'snapshot is oversized' ); + }; + await assert.rejects( + buildCodeReferencePreview( current.options, current.overrides ), + /snapshot is oversized/ + ); + const written = JSON.parse( + await readFile( path.join( current.root, 'build.json' ), 'utf8' ) + ); + assert.equal( written.buildStatus, 'failed' ); + assert.equal( written.sourceSha, SHA ); + assert.equal( written.snapshotFilename, null ); + assert.equal( written.buildError, 'snapshot is oversized' ); +} ); + +test( 'advisory failures are recorded without rejecting the build', async () => { + const current = await fixture( [ 'catastrophic undercount' ] ); + const result = await buildCodeReferencePreview( + current.options, + current.overrides + ); + assert.equal( result.metadata.validationStatus, 'failed' ); + assert.deepEqual( result.metadata.validationFailures, [ + 'catastrophic undercount', + ] ); +} ); + +test( 'behavioral failures prevent passed metadata in advisory mode', async () => { + const current = await fixture(); + current.overrides.validateSnapshot = async () => ( { + failures: [ 'class route returned HTTP 404.' ], + checks: { class: 404 }, + } ); + const result = await buildCodeReferencePreview( + current.options, + current.overrides + ); + assert.equal( result.metadata.validationStatus, 'failed' ); + assert.deepEqual( result.metadata.validationFailures, [ + 'class route returned HTTP 404.', + ] ); + assert.deepEqual( result.metadata.behavior.checks, { class: 404 } ); +} ); + +test( 'enforcement rejects only after failed validation metadata is written', async () => { + const current = await fixture( [ 'catastrophic undercount' ], true ); + await assert.rejects( + buildCodeReferencePreview( current.options, current.overrides ), + /catastrophic undercount/ + ); + const written = JSON.parse( + await readFile( path.join( current.root, 'build.json' ), 'utf8' ) + ); + assert.equal( written.validationStatus, 'failed' ); +} ); From b1cdc8119c8806251c2e50192051c978e2597d89 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 12:57:06 +0400 Subject: [PATCH 10/59] Build/Test Tools: Stop executing preview source during import The parser importer includes the Core version file. Pointing every record at the pull request source let untrusted PHP run during snapshot import. Give that one record a trusted empty replacement and create it before import. Route and search checks also accepted generic responses. Require representative symbol content and the expected search result path. Non-blocking: imported WordPress version metadata remains unset. Exact source-link behavior is deferred. --- .../docs-playground-preview/dependencies.json | 33 ++++++++++--- .../docs-playground-preview/lib/final.mjs | 17 +++++++ .../docs-playground-preview/lib/parser.mjs | 48 ++++++++++++++----- .../docs-playground-preview/lib/validate.mjs | 14 ++++-- .../php/safe-version.php | 8 ++++ .../test/final.test.mjs | 15 +++++- .../test/parser.test.mjs | 32 ++++++++++--- .../test/validate.test.mjs | 43 +++++++++++++---- 8 files changed, 169 insertions(+), 41 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/php/safe-version.php diff --git a/.github/docs-playground-preview/dependencies.json b/.github/docs-playground-preview/dependencies.json index 5745399688474..6351a45e3e529 100644 --- a/.github/docs-playground-preview/dependencies.json +++ b/.github/docs-playground-preview/dependencies.json @@ -61,16 +61,35 @@ "filters": 1000 }, "routes": { - "index": "/reference/", - "class": "/reference/classes/wp_html_tag_processor/", - "method": "/reference/classes/wp_html_tag_processor/next_tag/", - "function": "/reference/functions/wp_parse_args/", - "hook": "/reference/hooks/init/", - "filter": "/reference/hooks/the_content/" + "index": { + "path": "/reference/", + "expectedText": "Code Reference" + }, + "class": { + "path": "/reference/classes/wp_html_tag_processor/", + "expectedText": "WP_HTML_Tag_Processor" + }, + "method": { + "path": "/reference/classes/wp_html_tag_processor/next_tag/", + "expectedText": "next_tag" + }, + "function": { + "path": "/reference/functions/wp_parse_args/", + "expectedText": "wp_parse_args" + }, + "hook": { + "path": "/reference/hooks/init/", + "expectedText": "init" + }, + "filter": { + "path": "/reference/hooks/the_content/", + "expectedText": "the_content" + } }, "search": { "path": "/?s=wp_parse_args&post_type=wp-parser-function", - "expectedText": "wp_parse_args" + "expectedText": "wp_parse_args", + "expectedPath": "/reference/functions/wp_parse_args/" } } } diff --git a/.github/scripts/docs-playground-preview/lib/final.mjs b/.github/scripts/docs-playground-preview/lib/final.mjs index 059e64ca69132..cffa6a8d145dd 100644 --- a/.github/scripts/docs-playground-preview/lib/final.mjs +++ b/.github/scripts/docs-playground-preview/lib/final.mjs @@ -36,11 +36,24 @@ export function createFinalBlueprint( inputs ) { zipFile: bundled( 'base.zip' ), extractToPath: '/', }, + { + step: 'mkdir', + path: '/tmp/docs-preview-version', + }, + { + step: 'mkdir', + path: '/tmp/docs-preview-version/wp-includes', + }, { step: 'writeFile', path: '/tmp/reference.json', data: bundled( 'reference.json' ), }, + { + step: 'writeFile', + path: '/tmp/docs-preview-version/wp-includes/version.php', + data: bundled( 'safe-version.php' ), + }, { step: 'wp-cli', command: @@ -97,6 +110,10 @@ export async function packageFinalSnapshot( inputs, options ) { path.join( PHP_ROOT, 'complete-import.php' ), path.join( work, 'complete-import.php' ) ); + await copyFile( + path.join( PHP_ROOT, 'safe-version.php' ), + path.join( work, 'safe-version.php' ) + ); await writeFile( path.join( work, 'runtime.php' ), renderRuntimePlugin( options.provenance ) diff --git a/.github/scripts/docs-playground-preview/lib/parser.mjs b/.github/scripts/docs-playground-preview/lib/parser.mjs index fc9fccef53b26..5f1f346c2e4e3 100644 --- a/.github/scripts/docs-playground-preview/lib/parser.mjs +++ b/.github/scripts/docs-playground-preview/lib/parser.mjs @@ -5,6 +5,8 @@ import { stageCorePhp } from './files.mjs'; import { run } from './process.mjs'; const HOOK_TYPE = /^(?:action|filter)(?:_(?:deprecated|reference))?$/; +const IMPORT_SOURCE_ROOT = '/tmp/docs-preview-source'; +const SAFE_VERSION_ROOT = '/tmp/docs-preview-version'; function hooksIn( value ) { return Array.isArray( value?.hooks ) ? value.hooks : []; @@ -12,8 +14,14 @@ function hooksIn( value ) { function countHooks( hooks, counts ) { for ( const hook of hooks ) { - if ( ! hook || typeof hook !== 'object' || ! HOOK_TYPE.test( hook.type ) ) { - throw new Error( 'Parser JSON contains a hook with an invalid type.' ); + if ( + ! hook || + typeof hook !== 'object' || + ! HOOK_TYPE.test( hook.type ) + ) { + throw new Error( + 'Parser JSON contains a hook with an invalid type.' + ); } if ( hook.type.startsWith( 'action' ) ) { counts.hooks++; @@ -35,16 +43,24 @@ export function inspectParserRecords( records, minimumSymbols ) { filters: 0, }; for ( const record of records ) { - if ( ! record || typeof record !== 'object' || typeof record.path !== 'string' ) { + if ( + ! record || + typeof record !== 'object' || + typeof record.path !== 'string' + ) { throw new Error( 'Parser JSON contains an invalid file record.' ); } if ( record.path.startsWith( 'wp-content/plugins/' ) || record.path.startsWith( 'wp-content/themes/' ) ) { - throw new Error( `Parser JSON contains excluded source: ${ record.path }.` ); + throw new Error( + `Parser JSON contains excluded source: ${ record.path }.` + ); } - const functions = Array.isArray( record.functions ) ? record.functions : []; + const functions = Array.isArray( record.functions ) + ? record.functions + : []; const classes = Array.isArray( record.classes ) ? record.classes : []; counts.functions += functions.length; counts.classes += classes.length; @@ -59,15 +75,21 @@ export function inspectParserRecords( records, minimumSymbols ) { } } countHooks( hooksIn( record ), counts ); - record.root = '/tmp/docs-preview-source'; + record.root = + record.path === 'wp-includes/version.php' + ? SAFE_VERSION_ROOT + : IMPORT_SOURCE_ROOT; } - const failures = records.length === 0 ? [ 'Parser produced no file records.' ] : []; - failures.push( ...Object.entries( minimumSymbols ) - .filter( ( [ type, minimum ] ) => counts[ type ] < minimum ) - .map( - ( [ type, minimum ] ) => - `Parser produced ${ counts[ type ] } ${ type }; expected at least ${ minimum }.` - ) ); + const failures = + records.length === 0 ? [ 'Parser produced no file records.' ] : []; + failures.push( + ...Object.entries( minimumSymbols ) + .filter( ( [ type, minimum ] ) => counts[ type ] < minimum ) + .map( + ( [ type, minimum ] ) => + `Parser produced ${ counts[ type ] } ${ type }; expected at least ${ minimum }.` + ) + ); return { records: records.length, counts, failures }; } diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs index d9346326b17d0..be2c745bc6be0 100644 --- a/.github/scripts/docs-playground-preview/lib/validate.mjs +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -235,18 +235,18 @@ export async function inspectSnapshotBehavior( inputs, options ) { } } - for ( const [ name, route ] of Object.entries( + for ( const [ name, target ] of Object.entries( inputs.dependencies.validation.routes ) ) { try { - const response = await request( route ); + const response = await request( target.path ); checks[ name ] = response.status; if ( response.status !== 200 ) { failures.push( `${ name } route returned HTTP ${ response.status }.` ); } - const requested = new URL( route, options.baseUrl ); + const requested = new URL( target.path, options.baseUrl ); if ( ! response.url || new URL( response.url ).pathname !== requested.pathname @@ -255,6 +255,11 @@ export async function inspectSnapshotBehavior( inputs, options ) { `${ name } route redirected away from its stable path.` ); } + if ( ! response.body.includes( target.expectedText ) ) { + failures.push( + `${ name } route is missing its representative symbol.` + ); + } checkBanner( name, response.body, options.provenance, failures ); } catch ( error ) { failures.push( `${ name } route failed: ${ error.message }` ); @@ -267,7 +272,8 @@ export async function inspectSnapshotBehavior( inputs, options ) { checks.search = response.status; if ( response.status !== 200 || - ! response.body.includes( search.expectedText ) + ! response.body.includes( search.expectedText ) || + ! response.body.includes( search.expectedPath ) ) { failures.push( 'Local Code Reference search did not return the expected result.' diff --git a/.github/scripts/docs-playground-preview/php/safe-version.php b/.github/scripts/docs-playground-preview/php/safe-version.php new file mode 100644 index 0000000000000..df80505a83c91 --- /dev/null +++ b/.github/scripts/docs-playground-preview/php/safe-version.php @@ -0,0 +1,8 @@ + blueprint.steps.map( ( step ) => step.step ), [ 'unzip', + 'mkdir', + 'mkdir', + 'writeFile', 'writeFile', 'wp-cli', 'writeFile', @@ -40,7 +43,17 @@ test( 'the final Blueprint restores the base before the complete import', () => ] ); assert.equal( blueprint.steps[ 0 ].extractToPath, '/' ); - assert.match( blueprint.steps[ 2 ].command, /parser import.+--quick/ ); + assert.equal( blueprint.steps[ 1 ].path, '/tmp/docs-preview-version' ); + assert.equal( + blueprint.steps[ 2 ].path, + '/tmp/docs-preview-version/wp-includes' + ); + assert.equal( + blueprint.steps[ 4 ].path, + '/tmp/docs-preview-version/wp-includes/version.php' + ); + assert.equal( blueprint.steps[ 4 ].data.path, 'safe-version.php' ); + assert.match( blueprint.steps[ 5 ].command, /parser import.+--quick/ ); assert.equal( blueprint.steps.at( -3 ).path, '/wordpress/wp-content/plugins/phpdoc-parser' diff --git a/.github/scripts/docs-playground-preview/test/parser.test.mjs b/.github/scripts/docs-playground-preview/test/parser.test.mjs index 187f8a9f8160c..8d4f33e09cb86 100644 --- a/.github/scripts/docs-playground-preview/test/parser.test.mjs +++ b/.github/scripts/docs-playground-preview/test/parser.test.mjs @@ -4,10 +4,7 @@ import os from 'node:os'; import path from 'node:path'; import { test } from 'node:test'; -import { - generateParserJson, - inspectParserRecords, -} from '../lib/parser.mjs'; +import { generateParserJson, inspectParserRecords } from '../lib/parser.mjs'; function records() { return [ @@ -16,14 +13,20 @@ function records() { functions: [ { name: 'example', - hooks: [ { type: 'filter' }, { type: 'action_deprecated' } ], + hooks: [ + { type: 'filter' }, + { type: 'action_deprecated' }, + ], }, ], classes: [ { name: 'Example', methods: [ - { name: 'first', hooks: [ { type: 'filter_reference' } ] }, + { + name: 'first', + hooks: [ { type: 'filter_reference' } ], + }, { name: 'second', hooks: [] }, ], }, @@ -96,8 +99,23 @@ test( 'parser inspection rejects excluded bundled extension source', () => { ); } ); +test( 'the importer never receives pull-request PHP as its version include', () => { + const parsed = records(); + parsed.push( { + path: 'wp-includes/version.php', + functions: [], + classes: [], + hooks: [], + } ); + inspectParserRecords( parsed, {} ); + assert.equal( parsed[ 0 ].root, '/tmp/docs-preview-source' ); + assert.equal( parsed[ 1 ].root, '/tmp/docs-preview-version' ); +} ); + test( 'generateParserJson stages PHP, invokes the pinned parser, and normalizes output', async () => { - const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-parser-' ) ); + const temporary = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-parser-' ) + ); const source = path.join( temporary, 'wordpress/src' ); await mkdir( path.join( source, 'wp-includes' ), { recursive: true } ); await writeFile( path.join( source, 'wp-includes/version.php' ), '${ provenance.sourceRepository } ${ provenance.sourceSha } 2026-08-09 12:34:56 UTC Build run example_result`, + ` example_result example_function`, 200, url ); } + const target = Object.values( + inputs().dependencies.validation.routes + ).find( ( route ) => url.endsWith( route.path ) ); return response( - ``, + ` ${ target.expectedText }`, 200, url ); From d1fd8a0b33672fe9a200a284d8a856e6815730bb Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:12:51 +0400 Subject: [PATCH 11/59] Build/Test Tools: Add the Code Reference pull request build Preview builds must use the exact fork head without write authority. Run only for the one-shot label or a labeled synchronize event, and bind the invariant base to one exact cache key. A repeated SHA must not burn another full import when its public snapshot is healthy. Reuse only after the Playground proxy returns the expected headers, bytes, and digest. A rerun bypasses reuse. A missing handoff is a build failure. Publication remains a separate trusted change; this slice is already at the complexity tripwire. --- .../lib/publication.mjs | 260 ++++++++++++++++++ .../scripts/docs-playground-preview/reuse.mjs | 179 ++++++++++++ .../test/publication.test.mjs | 217 +++++++++++++++ .../docs-playground-preview-build.yml | 137 +++++++++ 4 files changed, 793 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/publication.mjs create mode 100644 .github/scripts/docs-playground-preview/reuse.mjs create mode 100644 .github/scripts/docs-playground-preview/test/publication.test.mjs create mode 100644 .github/workflows/docs-playground-preview-build.yml diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs new file mode 100644 index 0000000000000..bc37805ff6b44 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -0,0 +1,260 @@ +import { createHash } from 'node:crypto'; + +export const RELEASE_TAG = 'code-reference-playground-preview'; +export const COMMENT_MARKER = ''; +export const PLAYGROUND_ORIGIN = 'https://playground.wordpress.net'; +export const CORS_PROXY = 'https://wordpress-playground-cors-proxy.net/'; + +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const FULL_DIGEST = /^[0-9a-f]{64}$/; +const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; + +function positiveInteger( value, label ) { + const number = Number( value ); + if ( ! Number.isSafeInteger( number ) || number < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } + return number; +} + +function assertRepository( repository, label ) { + if ( typeof repository !== 'string' || ! REPOSITORY.test( repository ) ) { + throw new Error( `${ label } must be an owner/repository.` ); + } +} + +function assertCommit( sha, label ) { + if ( typeof sha !== 'string' || ! FULL_COMMIT.test( sha ) ) { + throw new Error( `${ label } must be a full lowercase commit hash.` ); + } +} + +export function snapshotAssetName( identity ) { + const pullRequest = positiveInteger( + identity.pullRequestNumber, + 'pullRequestNumber' + ); + const runId = positiveInteger( identity.workflowRunId, 'workflowRunId' ); + const attempt = positiveInteger( + identity.workflowRunAttempt, + 'workflowRunAttempt' + ); + assertCommit( identity.sourceSha, 'sourceSha' ); + return `code-reference-pr-${ pullRequest }-${ identity.sourceSha }-${ runId }-${ attempt }.zip`; +} + +export function metadataAssetName( snapshotName ) { + if ( + typeof snapshotName !== 'string' || + ! snapshotName.endsWith( '.zip' ) + ) { + throw new Error( 'Snapshot asset name must end in .zip.' ); + } + return `${ snapshotName.slice( 0, -4 ) }.json`; +} + +export function releaseAssetUrl( repository, assetName ) { + assertRepository( repository, 'repository' ); + if ( + typeof assetName !== 'string' || + ! /^[A-Za-z0-9_.-]+$/.test( assetName ) + ) { + throw new Error( 'Release asset name is invalid.' ); + } + return `https://github.com/${ repository }/releases/download/${ RELEASE_TAG }/${ assetName }`; +} + +export function corsProxyUrl( publicUrl ) { + const parsed = new URL( publicUrl ); + if ( parsed.protocol !== 'https:' || parsed.hostname !== 'github.com' ) { + throw new Error( 'Only public GitHub asset URLs may use the proxy.' ); + } + return `${ CORS_PROXY }${ publicUrl }`; +} + +export function createLaunchBlueprint( snapshotUrl, runtime ) { + return { + $schema: runtime.blueprintSchema, + meta: { + title: 'WordPress Core Code Reference preview', + author: 'WordPress', + description: + 'Complete Core Code Reference generated from an exact commit.', + }, + preferredVersions: { + php: runtime.phpVersion, + wp: runtime.wordpressVersion, + }, + landingPage: '/reference/', + login: false, + features: { networking: false }, + steps: [ + { + step: 'unzip', + zipFile: { resource: 'url', url: corsProxyUrl( snapshotUrl ) }, + extractToPath: '/', + }, + ], + }; +} + +export function playgroundUrl( snapshotUrl, runtime ) { + const blueprint = JSON.stringify( + createLaunchBlueprint( snapshotUrl, runtime ) + ); + return `${ PLAYGROUND_ORIGIN }/?blueprint-url=data:application/json,${ encodeURIComponent( + blueprint + ) }`; +} + +export async function validatePublicSnapshot( + publicUrl, + expected, + fetchImplementation = globalThis.fetch +) { + if ( + ! Number.isSafeInteger( expected.bytes ) || + expected.bytes < 1 || + expected.bytes > expected.maximumBytes + ) { + throw new Error( 'Published snapshot size is outside its boundary.' ); + } + if ( ! FULL_DIGEST.test( expected.sha256 || '' ) ) { + throw new Error( 'Published snapshot digest is invalid.' ); + } + const response = await fetchImplementation( corsProxyUrl( publicUrl ), { + headers: { Origin: PLAYGROUND_ORIGIN }, + } ); + if ( response.status !== 200 ) { + throw new Error( + `Public snapshot returned HTTP ${ response.status } through the proxy.` + ); + } + if ( response.headers.get( 'x-playground-cors-proxy' ) !== 'true' ) { + throw new Error( + 'Public snapshot response did not come through the proxy.' + ); + } + const allowedOrigin = response.headers.get( 'access-control-allow-origin' ); + if ( allowedOrigin !== PLAYGROUND_ORIGIN && allowedOrigin !== '*' ) { + throw new Error( + 'Public snapshot response does not allow Playground.' + ); + } + const bytes = Buffer.from( await response.arrayBuffer() ); + if ( bytes.byteLength !== expected.bytes ) { + throw new Error( + `Public snapshot has ${ bytes.byteLength } bytes; expected ${ expected.bytes }.` + ); + } + const digest = createHash( 'sha256' ).update( bytes ).digest( 'hex' ); + if ( digest !== expected.sha256 ) { + throw new Error( + 'Public snapshot digest does not match its metadata.' + ); + } + return { bytes: bytes.byteLength, sha256: digest }; +} + +export function validateReusableMetadata( metadata, expected ) { + if ( + ! metadata || + typeof metadata !== 'object' || + Array.isArray( metadata ) + ) { + throw new Error( 'Published metadata must be an object.' ); + } + if ( metadata.schemaVersion !== 1 ) { + throw new Error( 'Published metadata schema is unsupported.' ); + } + assertRepository( metadata.sourceRepository, 'sourceRepository' ); + assertRepository( expected.sourceRepository, 'expected sourceRepository' ); + assertCommit( metadata.sourceSha, 'sourceSha' ); + assertCommit( expected.sourceSha, 'expected sourceSha' ); + if ( + metadata.sourceRepository !== expected.sourceRepository || + metadata.sourceSha !== expected.sourceSha || + metadata.pullRequestNumber !== + positiveInteger( expected.pullRequestNumber, 'pullRequestNumber' ) + ) { + throw new Error( + 'Published metadata does not match the pull request.' + ); + } + if ( + metadata.buildStatus !== 'success' || + metadata.validationStatus !== 'passed' + ) { + throw new Error( + 'Published metadata does not describe a valid snapshot.' + ); + } + if ( + ! Number.isSafeInteger( metadata.snapshotBytes ) || + metadata.snapshotBytes < 1 || + metadata.snapshotBytes > expected.maximumBytes || + ! FULL_DIGEST.test( metadata.snapshotSha256 || '' ) + ) { + throw new Error( 'Published snapshot identity is invalid.' ); + } + const prefix = `code-reference-pr-${ metadata.pullRequestNumber }-${ metadata.sourceSha }-`; + if ( + typeof metadata.snapshotFilename !== 'string' || + ! metadata.snapshotFilename.startsWith( prefix ) || + ! /^code-reference-pr-\d+-[0-9a-f]{40}-\d+-\d+\.zip$/.test( + metadata.snapshotFilename + ) + ) { + throw new Error( 'Published snapshot filename is invalid.' ); + } + if ( + metadata.phpVersion !== '8.4' || + metadata.resolvedWordPressBeta?.channel !== 'beta' || + ! /^\d+\.\d+(?:\.\d+)?-(?:beta\d+|RC\d+)$/.test( + metadata.resolvedWordPressBeta.version || '' + ) || + metadata.resolvedWordPressBeta.downloadUrl !== + `https://downloads.wordpress.org/release/wordpress-${ metadata.resolvedWordPressBeta.version }.zip` + ) { + throw new Error( 'Published runtime identity is invalid.' ); + } + if ( ! FULL_DIGEST.test( metadata.dependencyManifestDigest || '' ) ) { + throw new Error( 'Published dependency identity is invalid.' ); + } + if ( + typeof metadata.generationTimestamp !== 'string' || + Number.isNaN( Date.parse( metadata.generationTimestamp ) ) + ) { + throw new Error( 'Published generation timestamp is invalid.' ); + } + return metadata; +} + +export function createReuseHandoff( published, identity ) { + validateReusableMetadata( published, { + ...identity, + maximumBytes: identity.maximumBytes, + } ); + return { + ...published, + handoffType: 'reuse', + sourceRepository: identity.sourceRepository, + pullRequestNumber: positiveInteger( + identity.pullRequestNumber, + 'pullRequestNumber' + ), + sourceSha: identity.sourceSha, + workflowRunId: String( + positiveInteger( identity.workflowRunId, 'workflowRunId' ) + ), + workflowRunAttempt: positiveInteger( + identity.workflowRunAttempt, + 'workflowRunAttempt' + ), + runUrl: identity.runUrl, + reusedSnapshot: { + assetName: published.snapshotFilename, + metadataAssetName: metadataAssetName( published.snapshotFilename ), + }, + }; +} diff --git a/.github/scripts/docs-playground-preview/reuse.mjs b/.github/scripts/docs-playground-preview/reuse.mjs new file mode 100644 index 0000000000000..da58eb718a71c --- /dev/null +++ b/.github/scripts/docs-playground-preview/reuse.mjs @@ -0,0 +1,179 @@ +#!/usr/bin/env node + +import { mkdir, writeFile } from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; +import path from 'node:path'; + +import { + RELEASE_TAG, + createReuseHandoff, + metadataAssetName, + validatePublicSnapshot, + validateReusableMetadata, +} from './lib/publication.mjs'; + +function argumentsFrom( values ) { + const options = {}; + for ( let index = 0; index < values.length; index += 2 ) { + const name = values[ index ]; + const value = values[ index + 1 ]; + if ( ! name?.startsWith( '--' ) || ! value ) { + throw new Error( `Invalid argument ${ name || '(missing)' }.` ); + } + options[ + name + .slice( 2 ) + .replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() ) + ] = value; + } + return options; +} + +async function apiJson( url, token, fetchImplementation ) { + const response = await fetchImplementation( url, { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${ token }`, + 'X-GitHub-Api-Version': '2022-11-28', + }, + } ); + if ( response.status === 404 ) { + return null; + } + if ( ! response.ok ) { + throw new Error( + `GitHub returned HTTP ${ response.status } for ${ url }.` + ); + } + return response.json(); +} + +async function releaseAssets( + repository, + releaseId, + token, + fetchImplementation +) { + const assets = []; + for ( let page = 1; ; page++ ) { + const batch = await apiJson( + `https://api.github.com/repos/${ repository }/releases/${ releaseId }/assets?per_page=100&page=${ page }`, + token, + fetchImplementation + ); + assets.push( ...batch ); + if ( batch.length < 100 ) { + return assets; + } + } +} + +export async function findReusablePreview( options ) { + const fetchImplementation = options.fetchImplementation || globalThis.fetch; + const release = await apiJson( + `https://api.github.com/repos/${ options.repository }/releases/tags/${ RELEASE_TAG }`, + options.token, + fetchImplementation + ); + if ( ! release ) { + return null; + } + const assets = await releaseAssets( + options.repository, + release.id, + options.token, + fetchImplementation + ); + const prefix = `code-reference-pr-${ options.pullRequestNumber }-${ options.sourceSha }-`; + const candidates = assets + .filter( + ( asset ) => + asset.name.startsWith( prefix ) && + asset.name.endsWith( '.json' ) + ) + .sort( ( left, right ) => + right.created_at.localeCompare( left.created_at ) + ); + for ( const candidate of candidates ) { + try { + const metadataResponse = await fetchImplementation( + candidate.browser_download_url + ); + if ( metadataResponse.status !== 200 ) { + throw new Error( + `Published metadata returned HTTP ${ metadataResponse.status }.` + ); + } + const published = validateReusableMetadata( + await metadataResponse.json(), + options + ); + if ( + candidate.name !== + metadataAssetName( published.snapshotFilename ) + ) { + throw new Error( + 'Published metadata asset name does not match.' + ); + } + const snapshot = assets.find( + ( asset ) => asset.name === published.snapshotFilename + ); + if ( ! snapshot ) { + throw new Error( 'Published snapshot asset is missing.' ); + } + await validatePublicSnapshot( + snapshot.browser_download_url, + { + bytes: published.snapshotBytes, + sha256: published.snapshotSha256, + maximumBytes: options.maximumBytes, + }, + fetchImplementation + ); + return createReuseHandoff( published, options ); + } catch ( error ) { + options.warning?.( + `Cannot reuse ${ candidate.name }: ${ error.message }` + ); + } + } + return null; +} + +async function main() { + const options = argumentsFrom( process.argv.slice( 2 ) ); + const handoff = await findReusablePreview( { + ...options, + maximumBytes: Number( options.maximumBytes ), + token: process.env.GITHUB_TOKEN, + warning: ( message ) => console.warn( `::warning::${ message }` ), + } ); + if ( handoff ) { + await mkdir( path.dirname( options.output ), { recursive: true } ); + await writeFile( + options.output, + `${ JSON.stringify( handoff, null, 2 ) }\n` + ); + } + if ( process.env.GITHUB_OUTPUT ) { + await writeFile( + process.env.GITHUB_OUTPUT, + `reused=${ handoff ? 'true' : 'false' }\n`, + { flag: 'a' } + ); + } +} + +if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { + main().catch( async ( error ) => { + console.warn( + `::warning::Same-SHA reuse check failed: ${ error.message }` + ); + if ( process.env.GITHUB_OUTPUT ) { + await writeFile( process.env.GITHUB_OUTPUT, 'reused=false\n', { + flag: 'a', + } ).catch( () => {} ); + } + } ); +} diff --git a/.github/scripts/docs-playground-preview/test/publication.test.mjs b/.github/scripts/docs-playground-preview/test/publication.test.mjs new file mode 100644 index 0000000000000..353f8e10f9bc8 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/publication.test.mjs @@ -0,0 +1,217 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { test } from 'node:test'; + +import { + PLAYGROUND_ORIGIN, + createLaunchBlueprint, + createReuseHandoff, + metadataAssetName, + playgroundUrl, + releaseAssetUrl, + snapshotAssetName, + validatePublicSnapshot, + validateReusableMetadata, +} from '../lib/publication.mjs'; +import { findReusablePreview } from '../reuse.mjs'; + +const identity = { + repository: 'WordPress/wordpress-develop', + sourceRepository: 'contributor/wordpress-develop', + pullRequestNumber: 123, + sourceSha: 'a'.repeat( 40 ), + workflowRunId: '456', + workflowRunAttempt: 1, + runUrl: 'https://github.com/WordPress/wordpress-develop/actions/runs/456/attempts/1', + maximumBytes: 104857600, +}; + +function published( bytes = Buffer.from( 'snapshot' ) ) { + const snapshotFilename = snapshotAssetName( identity ); + return { + schemaVersion: 1, + sourceRepository: identity.sourceRepository, + pullRequestNumber: identity.pullRequestNumber, + sourceSha: identity.sourceSha, + workflowRunId: identity.workflowRunId, + workflowRunAttempt: identity.workflowRunAttempt, + runUrl: identity.runUrl, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename, + snapshotBytes: bytes.byteLength, + snapshotSha256: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + validationFailures: [], + generationTimestamp: '2026-08-09T12:34:56.000Z', + }; +} + +function headers( values ) { + return { get: ( name ) => values[ name.toLowerCase() ] || null }; +} + +test( 'immutable asset names bind the PR, SHA, run, and attempt', () => { + const snapshot = snapshotAssetName( identity ); + assert.equal( + snapshot, + `code-reference-pr-123-${ 'a'.repeat( 40 ) }-456-1.zip` + ); + assert.equal( + metadataAssetName( snapshot ), + `code-reference-pr-123-${ 'a'.repeat( 40 ) }-456-1.json` + ); + assert.throws( + () => snapshotAssetName( { ...identity, sourceSha: 'trunk' } ), + /full lowercase commit/ + ); +} ); + +test( 'the launch Blueprint opens the snapshot at the reference index', () => { + const snapshot = snapshotAssetName( identity ); + const publicUrl = releaseAssetUrl( identity.repository, snapshot ); + const runtime = { + blueprintSchema: + 'https://playground.wordpress.net/blueprint-schema.json', + phpVersion: '8.4', + wordpressVersion: '7.2-beta1', + }; + const blueprint = createLaunchBlueprint( publicUrl, runtime ); + assert.equal( blueprint.landingPage, '/reference/' ); + assert.equal( blueprint.login, false ); + assert.equal( blueprint.features.networking, false ); + assert.equal( blueprint.steps[ 0 ].extractToPath, '/' ); + assert.match( + blueprint.steps[ 0 ].zipFile.url, + /^https:\/\/wordpress-playground-cors-proxy\.net\/https:\/\/github\.com\// + ); + assert.match( + decodeURIComponent( playgroundUrl( publicUrl, runtime ) ), + /"landingPage":"\/reference\/"/ + ); +} ); + +test( 'public delivery is checked by status, headers, size, and digest', async () => { + const bytes = Buffer.from( 'snapshot' ); + const expected = published( bytes ); + const result = await validatePublicSnapshot( + releaseAssetUrl( identity.repository, expected.snapshotFilename ), + { + bytes: expected.snapshotBytes, + sha256: expected.snapshotSha256, + maximumBytes: identity.maximumBytes, + }, + async ( url, options ) => { + assert.match( url, /wordpress-playground-cors-proxy/ ); + assert.equal( options.headers.Origin, PLAYGROUND_ORIGIN ); + return { + status: 200, + headers: headers( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } ), + arrayBuffer: async () => bytes, + }; + } + ); + assert.equal( result.sha256, expected.snapshotSha256 ); + + await assert.rejects( + validatePublicSnapshot( + 'https://github.com/WordPress/wordpress-develop/releases/download/x/y.zip', + { + bytes: bytes.byteLength, + sha256: '0'.repeat( 64 ), + maximumBytes: identity.maximumBytes, + }, + async () => ( { + status: 200, + headers: headers( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } ), + arrayBuffer: async () => bytes, + } ) + ), + /digest/ + ); +} ); + +test( 'reusable metadata must identify a passed same-PR snapshot', () => { + const metadata = published(); + assert.equal( validateReusableMetadata( metadata, identity ), metadata ); + assert.throws( + () => + validateReusableMetadata( + { ...metadata, validationStatus: 'failed' }, + identity + ), + /valid snapshot/ + ); + assert.throws( + () => + validateReusableMetadata( + { ...metadata, snapshotBytes: 104857601 }, + identity + ), + /identity is invalid/ + ); +} ); + +test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () => { + const bytes = Buffer.from( 'snapshot' ); + const metadata = published( bytes ); + const metadataName = metadataAssetName( metadata.snapshotFilename ); + const assets = [ + { + name: metadataName, + created_at: '2026-08-09T13:00:00Z', + browser_download_url: 'https://github.com/metadata.json', + }, + { + name: metadata.snapshotFilename, + created_at: '2026-08-09T13:00:00Z', + browser_download_url: 'https://github.com/snapshot.zip', + }, + ]; + const fetchImplementation = async ( url ) => { + if ( url.includes( '/releases/tags/' ) ) { + return { ok: true, status: 200, json: async () => ( { id: 9 } ) }; + } + if ( url.includes( '/releases/9/assets' ) ) { + return { ok: true, status: 200, json: async () => assets }; + } + if ( url === 'https://github.com/metadata.json' ) { + return { status: 200, json: async () => metadata }; + } + assert.match( url, /wordpress-playground-cors-proxy/ ); + return { + status: 200, + headers: headers( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } ), + arrayBuffer: async () => bytes, + }; + }; + const handoff = await findReusablePreview( { + ...identity, + token: 'read-token', + fetchImplementation, + } ); + assert.equal( handoff.handoffType, 'reuse' ); + assert.equal( handoff.workflowRunId, identity.workflowRunId ); + assert.equal( handoff.reusedSnapshot.assetName, metadata.snapshotFilename ); + assert.equal( handoff.reusedSnapshot.metadataAssetName, metadataName ); + assert.deepEqual( + createReuseHandoff( metadata, identity ).reusedSnapshot, + handoff.reusedSnapshot + ); +} ); diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml new file mode 100644 index 0000000000000..a09a4878e7aa0 --- /dev/null +++ b/.github/workflows/docs-playground-preview-build.yml @@ -0,0 +1,137 @@ +name: Code Reference Playground Preview Build + +on: + pull_request: + branches: + - trunk + types: [ labeled, synchronize ] + +# A newer head makes every older build obsolete for this pull request. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +# Pull-request code receives no write authority or repository secrets. +permissions: {} + +jobs: + build: + name: Build Code Reference snapshot + if: >- + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) && + github.event.pull_request.base.ref == 'trunk' && + ( ( github.event.action == 'labeled' && github.event.label.name == 'docs-preview' ) || + ( github.event.action == 'synchronize' && contains( github.event.pull_request.labels.*.name, 'docs-preview' ) ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: read + env: + DEPLOYMENT_REPOSITORY: ${{ github.repository }} + SOURCE_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }} + SOURCE_SHA: ${{ github.event.pull_request.head.sha }} + PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + WORKFLOW_RUN_ID: ${{ github.run_id }} + WORKFLOW_RUN_ATTEMPT: ${{ github.run_attempt }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + HANDOFF_DIRECTORY: ${{ github.workspace }}/handoff + RESOLVED_INPUTS: ${{ runner.temp }}/docs-preview-resolved-inputs.json + CACHE_ROOT: ${{ runner.temp }}/docs-preview-cache + WORK_ROOT: ${{ runner.temp }}/docs-preview-work + SNAPSHOT_NAME: code-reference-pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-${{ github.run_id }}-${{ github.run_attempt }}.zip + steps: + - name: Check out the exact pull-request head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Reuse a healthy public snapshot for the same SHA + id: reuse + if: ${{ github.run_attempt == 1 }} + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + node .github/scripts/docs-playground-preview/reuse.mjs + --repository "$DEPLOYMENT_REPOSITORY" + --source-repository "$SOURCE_REPOSITORY" + --pull-request-number "$PULL_REQUEST_NUMBER" + --source-sha "$SOURCE_SHA" + --workflow-run-id "$WORKFLOW_RUN_ID" + --workflow-run-attempt "$WORKFLOW_RUN_ATTEMPT" + --run-url "$RUN_URL" + --maximum-bytes 104857600 + --output "$HANDOFF_DIRECTORY/build.json" + + - name: Set up the pinned PHP and Composer versions + if: ${{ steps.reuse.outputs.reused != 'true' }} + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 + with: + php-version: '8.4' + tools: composer:2.8.12 + coverage: none + + - name: Resolve the exact build and cache identity + id: resolve + if: ${{ steps.reuse.outputs.reused != 'true' }} + run: >- + npm --prefix .github/docs-playground-preview run build -- + --resolve-only + --source "$GITHUB_WORKSPACE" + --source-repository "$SOURCE_REPOSITORY" + --source-sha "$SOURCE_SHA" + --pull-request "$PULL_REQUEST_NUMBER" + --run-id "$WORKFLOW_RUN_ID" + --run-attempt "$WORKFLOW_RUN_ATTEMPT" + --run-url "$RUN_URL" + --runner-image ubuntu-24.04 + --cache-root "$CACHE_ROOT" + --work-root "$WORK_ROOT" + --inputs-output "$RESOLVED_INPUTS" + --metadata "$HANDOFF_DIRECTORY/build.json" + + - name: Restore the exact invariant site base + if: ${{ steps.reuse.outputs.reused != 'true' }} + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ steps.resolve.outputs.cache-directory }} + key: ${{ steps.resolve.outputs.cache-key }} + + # Administrator: enable enforcement in Settings > Secrets and variables > + # Actions > Variables by creating or updating DOCS_PREVIEW_ENFORCE to true. + - name: Build and validate the Code Reference snapshot + if: ${{ steps.reuse.outputs.reused != 'true' }} + env: + DOCS_PREVIEW_ENFORCE: ${{ vars.DOCS_PREVIEW_ENFORCE }} + run: >- + npm --prefix .github/docs-playground-preview run build -- + --source "$GITHUB_WORKSPACE" + --source-repository "$SOURCE_REPOSITORY" + --source-sha "$SOURCE_SHA" + --pull-request "$PULL_REQUEST_NUMBER" + --run-id "$WORKFLOW_RUN_ID" + --run-attempt "$WORKFLOW_RUN_ATTEMPT" + --run-url "$RUN_URL" + --runner-image ubuntu-24.04 + --cache-root "$CACHE_ROOT" + --work-root "$WORK_ROOT" + --resolved-inputs "$RESOLVED_INPUTS" + --output "$HANDOFF_DIRECTORY/$SNAPSHOT_NAME" + --metadata "$HANDOFF_DIRECTORY/build.json" + + - name: Upload the terminal publisher handoff + if: ${{ always() && ! cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: docs-preview-handoff-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ env.HANDOFF_DIRECTORY }} + if-no-files-found: error + retention-days: 1 From 13e0aab266d50a5526caab81f236fb880f40c05e Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:21:12 +0400 Subject: [PATCH 12/59] Build/Test Tools: Validate Code Reference publication handoffs The publisher must not infer trust from a successful build job. Bind every handoff to the enabled repository, exact workflow attempt, fetched pull request, trunk base, head repository, head SHA, schema, filename, size, and digest. Fresh and reused candidates share the same runtime and dependency checks. Failed or advisory results are terminal states, never publishable candidates. The snapshot is hashed but never opened. The network layer must refresh the latest run immediately before every mutation. A cached lookup defeats same-SHA supersession. --- .../docs-playground-preview/lib/publisher.mjs | 302 ++++++++++++++++++ .../test/publisher.test.mjs | 287 +++++++++++++++++ 2 files changed, 589 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/publisher.mjs create mode 100644 .github/scripts/docs-playground-preview/test/publisher.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs new file mode 100644 index 0000000000000..074cd99680217 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -0,0 +1,302 @@ +import { stat } from 'node:fs/promises'; +import path from 'node:path'; + +import { isDeploymentEnabled } from './config.mjs'; +import { sha256File } from './files.mjs'; +import { + COMMENT_MARKER, + corsProxyUrl, + metadataAssetName, + playgroundUrl, + releaseAssetUrl, + snapshotAssetName, + validateReusableMetadata, +} from './publication.mjs'; + +export const BUILD_WORKFLOW_NAME = 'Code Reference Playground Preview Build'; +export const SNAPSHOT_BYTES_LIMIT = 104857600; + +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const FULL_DIGEST = /^[0-9a-f]{64}$/; +const BLUEPRINT_SCHEMA = + 'https://playground.wordpress.net/blueprint-schema.json'; + +function positiveInteger( value, label ) { + const number = Number( value ); + if ( ! Number.isSafeInteger( number ) || number < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } + return number; +} + +function timestamp( value, label ) { + if ( + typeof value !== 'string' || + Number.isNaN( Date.parse( value ) ) || + ! value.endsWith( 'Z' ) + ) { + throw new Error( `${ label } must be a UTC timestamp.` ); + } + return value; +} + +function headRepository( value ) { + return value?.full_name || value?.repo?.full_name || null; +} + +export function validatePublicationContext( context ) { + if ( + ! isDeploymentEnabled( context.repository, context.stagingVariable ) + ) { + throw new Error( + 'Docs preview publication is disabled in this repository.' + ); + } + const runId = positiveInteger( context.run?.id, 'Workflow run id' ); + const runAttempt = positiveInteger( + context.run?.run_attempt, + 'Workflow run attempt' + ); + if ( + runId !== positiveInteger( context.triggerRunId, 'Trigger run id' ) || + runAttempt !== + positiveInteger( context.triggerRunAttempt, 'Trigger run attempt' ) + ) { + throw new Error( + 'The triggering workflow attempt is no longer current.' + ); + } + if ( + context.run.name !== BUILD_WORKFLOW_NAME || + context.run.event !== 'pull_request' + ) { + throw new Error( 'The source workflow identity is invalid.' ); + } + if ( context.run.status !== 'completed' ) { + throw new Error( 'The source workflow is not terminal.' ); + } + const pullRequestNumber = positiveInteger( + context.pullRequest?.number, + 'Pull request number' + ); + if ( context.pullRequest.base?.ref !== 'trunk' ) { + throw new Error( 'The pull request does not target trunk.' ); + } + const sourceSha = context.pullRequest.head?.sha; + if ( + ! FULL_COMMIT.test( sourceSha || '' ) || + context.run.head_sha !== sourceSha + ) { + throw new Error( + 'The workflow run does not match the pull request head.' + ); + } + const sourceRepository = headRepository( context.pullRequest.head ); + if ( + ! sourceRepository || + headRepository( context.run.head_repository ) !== sourceRepository + ) { + throw new Error( + 'The workflow run does not match the pull request repository.' + ); + } + return { + ...context, + pullRequestNumber, + sourceRepository, + sourceSha, + workflowRunId: runId, + workflowRunAttempt: runAttempt, + runUrl: `https://github.com/${ context.repository }/actions/runs/${ runId }`, + }; +} + +export function assertLatestAuthorized( context ) { + const current = validatePublicationContext( context ); + if ( + context.latestRun?.id !== current.workflowRunId || + context.latestRun?.run_attempt !== current.workflowRunAttempt + ) { + throw new Error( 'A newer docs preview run superseded this attempt.' ); + } + if ( current.pullRequest.state !== 'open' ) { + throw new Error( 'The pull request is no longer open.' ); + } + const hasLabel = current.pullRequest.labels?.some( + ( label ) => label.name === 'docs-preview' + ); + if ( ! hasLabel && current.workflowRunAttempt === 1 ) { + throw new Error( 'The docs-preview request is no longer authorized.' ); + } + return current; +} + +function validateCommonHandoff( metadata, context ) { + if ( + ! metadata || + typeof metadata !== 'object' || + Array.isArray( metadata ) + ) { + throw new Error( 'Handoff metadata must be an object.' ); + } + if ( metadata.schemaVersion !== 1 ) { + throw new Error( 'Handoff metadata schema is unsupported.' ); + } + if ( + metadata.sourceRepository !== context.sourceRepository || + metadata.pullRequestNumber !== context.pullRequestNumber || + metadata.sourceSha !== context.sourceSha || + String( metadata.workflowRunId ) !== String( context.workflowRunId ) || + metadata.workflowRunAttempt !== context.workflowRunAttempt || + metadata.runUrl !== context.runUrl + ) { + throw new Error( 'Handoff metadata does not match the workflow run.' ); + } + timestamp( metadata.generationTimestamp, 'Generation timestamp' ); +} + +function validateSnapshotIdentity( metadata ) { + if ( + ! Number.isSafeInteger( metadata.snapshotBytes ) || + metadata.snapshotBytes < 1 || + metadata.snapshotBytes > SNAPSHOT_BYTES_LIMIT + ) { + throw new Error( 'Snapshot size is outside the 100 MiB boundary.' ); + } + if ( ! FULL_DIGEST.test( metadata.snapshotSha256 || '' ) ) { + throw new Error( 'Snapshot digest is invalid.' ); + } +} + +export function inspectHandoff( metadata, rawContext ) { + const context = validatePublicationContext( rawContext ); + validateCommonHandoff( metadata, context ); + if ( metadata.buildStatus === 'failed' ) { + return { kind: 'failed', metadata, context }; + } + if ( metadata.buildStatus !== 'success' ) { + throw new Error( 'Handoff build status is invalid.' ); + } + if ( metadata.validationStatus === 'failed' ) { + return { kind: 'invalid', metadata, context }; + } + if ( metadata.validationStatus !== 'passed' ) { + throw new Error( 'Handoff validation status is invalid.' ); + } + validateSnapshotIdentity( metadata ); + validateReusableMetadata( metadata, { + sourceRepository: context.sourceRepository, + pullRequestNumber: context.pullRequestNumber, + sourceSha: context.sourceSha, + maximumBytes: SNAPSHOT_BYTES_LIMIT, + } ); + if ( metadata.handoffType === 'reuse' ) { + if ( + metadata.reusedSnapshot?.assetName !== metadata.snapshotFilename || + metadata.reusedSnapshot.metadataAssetName !== + metadataAssetName( metadata.snapshotFilename ) + ) { + throw new Error( 'Reusable asset identity is invalid.' ); + } + return { kind: 'reuse', metadata, context }; + } + if ( metadata.handoffType !== undefined ) { + throw new Error( 'Handoff type is invalid.' ); + } + const expectedFilename = snapshotAssetName( context ); + if ( metadata.snapshotFilename !== expectedFilename ) { + throw new Error( 'Candidate snapshot filename is invalid.' ); + } + return { kind: 'candidate', metadata, context }; +} + +export async function validateCandidateFile( metadata, filename ) { + if ( path.basename( filename ) !== metadata.snapshotFilename ) { + throw new Error( + 'Candidate file does not match its metadata filename.' + ); + } + const candidate = await stat( filename ); + if ( ! candidate.isFile() || candidate.size !== metadata.snapshotBytes ) { + throw new Error( 'Candidate file size does not match its metadata.' ); + } + const digest = await sha256File( filename ); + if ( digest !== metadata.snapshotSha256 ) { + throw new Error( 'Candidate file digest does not match its metadata.' ); + } + return { bytes: candidate.size, sha256: digest }; +} + +export function createPublishedMetadata( metadata, repository, publishedAt ) { + timestamp( publishedAt, 'Publication timestamp' ); + const snapshotUrl = releaseAssetUrl( + repository, + metadata.snapshotFilename + ); + return { + ...metadata, + publication: { + publishedAt, + snapshotUrl, + snapshotProxyUrl: corsProxyUrl( snapshotUrl ), + playgroundUrl: playgroundUrl( snapshotUrl, { + blueprintSchema: BLUEPRINT_SCHEMA, + phpVersion: metadata.phpVersion, + wordpressVersion: metadata.resolvedWordPressBeta.version, + } ), + }, + }; +} + +function commitLink( repository, sha ) { + return `[${ sha }](https://github.com/${ repository }/commit/${ sha })`; +} + +function previousLink( previous ) { + if ( ! previous ) { + return ''; + } + return `\n\n[Latest successful docs preview](${ + previous.publication.playgroundUrl + }) — built from ${ commitLink( + previous.sourceRepository, + previous.sourceSha + ) }.`; +} + +export function renderPreviewComment( state ) { + const header = `${ COMMENT_MARKER }\n## Code Reference documentation preview`; + if ( state.status === 'ready' ) { + return `${ header }\n\n**Status:** Ready\n\n[Open Code Reference preview](${ + state.preview.publication.playgroundUrl + })\n\nSource: ${ commitLink( + state.preview.sourceRepository, + state.preview.sourceSha + ) } \nPublished: ${ + state.preview.publication.publishedAt + } \n[GitHub Actions run](${ state.runUrl })`; + } + if ( state.status === 'failed' ) { + return `${ header }\n\n**Status:** Latest attempt failed\n\nThe latest attempt for ${ commitLink( + state.sourceRepository, + state.sourceSha + ) } failed at ${ state.at }. [View the GitHub Actions run](${ + state.runUrl + }).${ previousLink( state.previous ) }`; + } + if ( state.status === 'stale' ) { + return `${ header }\n\n**Status:** Stale\n\nThe latest successful preview was built from ${ commitLink( + state.preview.sourceRepository, + state.preview.sourceSha + ) }, but the pull request is now at ${ commitLink( + state.currentRepository, + state.currentSha + ) }.\n\n[Latest successful docs preview](${ + state.preview.publication.playgroundUrl + })\n\nAdd the \`docs-preview\` label again to build the current commit.`; + } + if ( state.status === 'expired' ) { + return `${ header }\n\n**Status:** Expired\n\nThis pull request is closed or merged. Its Code Reference preview expired and is no longer live.`; + } + throw new Error( `Unknown preview comment state ${ state.status }.` ); +} diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs new file mode 100644 index 0000000000000..965f2ba7ef81f --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -0,0 +1,287 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { mkdtemp, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + assertLatestAuthorized, + createPublishedMetadata, + inspectHandoff, + renderPreviewComment, + validateCandidateFile, + validatePublicationContext, +} from '../lib/publisher.mjs'; +import { + COMMENT_MARKER, + metadataAssetName, + snapshotAssetName, +} from '../lib/publication.mjs'; + +const sha = 'a'.repeat( 40 ); +const bytes = Buffer.from( 'snapshot' ); + +function context() { + return { + repository: 'WordPress/wordpress-develop', + stagingVariable: '', + triggerRunId: 456, + triggerRunAttempt: 1, + latestRun: { id: 456, run_attempt: 1 }, + run: { + id: 456, + run_attempt: 1, + name: 'Code Reference Playground Preview Build', + event: 'pull_request', + status: 'completed', + head_sha: sha, + head_repository: { full_name: 'contributor/wordpress-develop' }, + pull_requests: [], + }, + pullRequest: { + number: 123, + state: 'open', + base: { ref: 'trunk' }, + head: { + sha, + repo: { full_name: 'contributor/wordpress-develop' }, + }, + labels: [ { name: 'docs-preview' } ], + }, + }; +} + +function metadata( overrides = {} ) { + const identity = { + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: 456, + workflowRunAttempt: 1, + }; + return { + schemaVersion: 1, + sourceRepository: 'contributor/wordpress-develop', + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: '456', + workflowRunAttempt: 1, + runUrl: 'https://github.com/WordPress/wordpress-develop/actions/runs/456', + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename: snapshotAssetName( identity ), + snapshotBytes: bytes.byteLength, + snapshotSha256: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + validationFailures: [], + generationTimestamp: '2026-08-09T12:34:56.000Z', + ...overrides, + }; +} + +test( 'the publisher binds the trigger to an enabled terminal PR run', () => { + const checked = validatePublicationContext( context() ); + assert.equal( checked.sourceSha, sha ); + assert.equal( checked.pullRequestNumber, 123 ); + assert.equal( + checked.runUrl, + 'https://github.com/WordPress/wordpress-develop/actions/runs/456' + ); + assert.throws( + () => + validatePublicationContext( { + ...context(), + repository: 'attacker/wordpress-develop', + } ), + /publication is disabled/ + ); + assert.throws( + () => + validatePublicationContext( { + ...context(), + triggerRunAttempt: 2, + } ), + /no longer current/ + ); + assert.throws( + () => + validatePublicationContext( { + ...context(), + run: { ...context().run, head_sha: 'c'.repeat( 40 ) }, + } ), + /does not match the pull request head/ + ); +} ); + +test( 'latest-wins requires the label except for an explicit rerun', () => { + assert.equal( assertLatestAuthorized( context() ).sourceSha, sha ); + const unlabeled = context(); + unlabeled.pullRequest.labels = []; + assert.throws( () => assertLatestAuthorized( unlabeled ), /authorized/ ); + const rerun = context(); + rerun.triggerRunAttempt = 2; + rerun.run.run_attempt = 2; + rerun.latestRun.run_attempt = 2; + rerun.pullRequest.labels = []; + assert.equal( assertLatestAuthorized( rerun ).workflowRunAttempt, 2 ); + assert.throws( + () => + assertLatestAuthorized( { + ...context(), + latestRun: { id: 789, run_attempt: 1 }, + } ), + /superseded/ + ); +} ); + +test( 'a fresh candidate must pass every publisher identity field', () => { + assert.equal( inspectHandoff( metadata(), context() ).kind, 'candidate' ); + for ( const [ name, value, error ] of [ + [ 'schemaVersion', 2, /schema/ ], + [ 'sourceSha', 'c'.repeat( 40 ), /workflow run/ ], + [ 'workflowRunAttempt', 2, /workflow run/ ], + [ 'phpVersion', '8.5', /runtime identity/ ], + [ 'dependencyManifestDigest', 'broken', /dependency identity/ ], + [ 'handoffType', 'unknown', /Handoff type/ ], + [ 'snapshotFilename', 'snapshot.zip', /filename/ ], + [ 'snapshotBytes', 104857601, /100 MiB/ ], + [ 'snapshotSha256', 'broken', /digest/ ], + ] ) { + assert.throws( + () => inspectHandoff( metadata( { [ name ]: value } ), context() ), + error + ); + } +} ); + +test( 'failed and advisory handoffs are terminal but not candidates', () => { + assert.equal( + inspectHandoff( + metadata( { + buildStatus: 'failed', + validationStatus: 'not-run', + } ), + context() + ).kind, + 'failed' + ); + assert.equal( + inspectHandoff( metadata( { validationStatus: 'failed' } ), context() ) + .kind, + 'invalid' + ); +} ); + +test( 'reuse identifies the exact existing snapshot and metadata assets', () => { + const current = metadata(); + const reused = { + ...current, + handoffType: 'reuse', + reusedSnapshot: { + assetName: current.snapshotFilename, + metadataAssetName: metadataAssetName( current.snapshotFilename ), + }, + }; + assert.equal( inspectHandoff( reused, context() ).kind, 'reuse' ); + assert.throws( + () => + inspectHandoff( + { + ...reused, + reusedSnapshot: { + ...reused.reusedSnapshot, + assetName: 'other.zip', + }, + }, + context() + ), + /Reusable asset identity/ + ); +} ); + +test( 'candidate bytes and digest are checked without opening the snapshot', async () => { + const temporary = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-publisher-' ) + ); + const current = metadata(); + const filename = path.join( temporary, current.snapshotFilename ); + await writeFile( filename, bytes ); + assert.deepEqual( await validateCandidateFile( current, filename ), { + bytes: bytes.byteLength, + sha256: current.snapshotSha256, + } ); + await writeFile( filename, 'changed!' ); + await assert.rejects( + validateCandidateFile( current, filename ), + /digest/ + ); +} ); + +test( 'published metadata contains the immutable public launch identity', () => { + const published = createPublishedMetadata( + metadata(), + 'WordPress/wordpress-develop', + '2026-08-09T13:00:00.000Z' + ); + assert.equal( + published.publication.publishedAt, + '2026-08-09T13:00:00.000Z' + ); + assert.match( published.publication.snapshotUrl, /releases\/download/ ); + assert.match( + published.publication.snapshotProxyUrl, + /wordpress-playground-cors-proxy/ + ); + assert.match( published.publication.playgroundUrl, /blueprint-url=/ ); +} ); + +test( 'the sticky comment has ready, failed, stale, and expired states', () => { + const preview = createPublishedMetadata( + metadata(), + 'WordPress/wordpress-develop', + '2026-08-09T13:00:00.000Z' + ); + const ready = renderPreviewComment( { + status: 'ready', + preview, + runUrl: preview.runUrl, + } ); + assert.match( ready, new RegExp( COMMENT_MARKER ) ); + assert.match( ready, /Status:\*\* Ready/ ); + assert.match( ready, new RegExp( sha ) ); + assert.equal( ready.match( /Open Code Reference preview/g ).length, 1 ); + + const failed = renderPreviewComment( { + status: 'failed', + sourceRepository: preview.sourceRepository, + sourceSha: 'c'.repeat( 40 ), + at: '2026-08-09T14:00:00.000Z', + runUrl: preview.runUrl, + previous: preview, + } ); + assert.match( failed, /Latest attempt failed/ ); + assert.equal( failed.match( /Latest successful docs preview/g ).length, 1 ); + + const stale = renderPreviewComment( { + status: 'stale', + preview, + currentRepository: preview.sourceRepository, + currentSha: 'c'.repeat( 40 ), + } ); + assert.match( stale, /Status:\*\* Stale/ ); + assert.match( stale, /add the `docs-preview` label again/i ); + assert.match( stale, new RegExp( sha ) ); + assert.match( stale, new RegExp( 'c'.repeat( 40 ) ) ); + + assert.match( + renderPreviewComment( { status: 'expired' } ), + /preview expired and is no longer live/ + ); +} ); From 976908d08dda5638c6586be167e9023f108f6363 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:26:56 +0400 Subject: [PATCH 13/59] Build/Test Tools: Add the Code Reference publisher transport Fork workflow runs do not reliably carry pull request associations. Resolve the open pull request from the exact head owner, branch, repository, and SHA instead of trusting an empty field. Latest-wins needs a fresh workflow lookup, including rerun attempts. Keep that query and the release, comment, and label calls behind one narrow GitHub API client so transaction ordering remains visible in the publisher. --- .../docs-playground-preview/lib/github.mjs | 216 ++++++++++++++++++ .../test/github.test.mjs | 165 +++++++++++++ 2 files changed, 381 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/github.mjs create mode 100644 .github/scripts/docs-playground-preview/test/github.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs new file mode 100644 index 0000000000000..cb104e84bd421 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -0,0 +1,216 @@ +import { COMMENT_MARKER, RELEASE_TAG } from './publication.mjs'; + +const API = 'https://api.github.com'; +const UPLOADS = 'https://uploads.github.com'; +const BUILD_WORKFLOW = 'docs-playground-preview-build.yml'; + +function query( values ) { + const parameters = new URLSearchParams(); + for ( const [ name, value ] of Object.entries( values ) ) { + if ( value !== undefined && value !== null ) { + parameters.set( name, String( value ) ); + } + } + return parameters.toString(); +} + +export class GitHubApi { + constructor( repository, token, fetchImplementation = globalThis.fetch ) { + this.repository = repository; + this.token = token; + this.fetch = fetchImplementation; + } + + async request( url, options = {} ) { + const headers = { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${ this.token }`, + 'X-GitHub-Api-Version': '2022-11-28', + ...options.headers, + }; + const response = await this.fetch( + url.startsWith( 'https://' ) ? url : `${ API }${ url }`, + { + ...options, + headers, + body: + options.json === undefined + ? options.body + : JSON.stringify( options.json ), + } + ); + if ( options.allowNotFound && response.status === 404 ) { + return null; + } + if ( ! response.ok ) { + const detail = await response.text(); + throw new Error( + `GitHub API returned HTTP ${ + response.status + } for ${ url }: ${ detail.slice( 0, 300 ) }` + ); + } + if ( response.status === 204 ) { + return null; + } + return response.json(); + } + + async pages( path, field = null ) { + const values = []; + for ( let page = 1; ; page++ ) { + const separator = path.includes( '?' ) ? '&' : '?'; + const response = await this.request( + `${ path }${ separator }per_page=100&page=${ page }` + ); + const batch = field ? response[ field ] : response; + values.push( ...batch ); + if ( batch.length < 100 ) { + return values; + } + } + } + + getRun( runId ) { + return this.request( + `/repos/${ this.repository }/actions/runs/${ runId }` + ); + } + + getPullRequest( number ) { + return this.request( `/repos/${ this.repository }/pulls/${ number }` ); + } + + async findPullRequestForRun( run ) { + const owner = run.head_repository?.owner?.login; + if ( ! owner || ! run.head_branch ) { + throw new Error( 'Workflow run has no fork head identity.' ); + } + const pulls = await this.pages( + `/repos/${ this.repository }/pulls?${ query( { + state: 'open', + base: 'trunk', + head: `${ owner }:${ run.head_branch }`, + } ) }` + ); + const matches = pulls.filter( + ( pullRequest ) => + pullRequest.head.sha === run.head_sha && + pullRequest.head.repo?.full_name === + run.head_repository.full_name + ); + if ( matches.length !== 1 ) { + throw new Error( + `Expected one pull request for the workflow run; found ${ matches.length }.` + ); + } + return matches[ 0 ]; + } + + async latestPreviewRun( run ) { + const runs = await this.pages( + `/repos/${ + this.repository + }/actions/workflows/${ BUILD_WORKFLOW }/runs?${ query( { + event: 'pull_request', + head_sha: run.head_sha, + } ) }`, + 'workflow_runs' + ); + const matching = runs + .filter( + ( candidate ) => + candidate.head_sha === run.head_sha && + candidate.head_branch === run.head_branch && + candidate.head_repository?.full_name === + run.head_repository?.full_name + ) + .sort( ( left, right ) => right.id - left.id ); + if ( ! matching[ 0 ] ) { + throw new Error( 'No current docs preview run matches this head.' ); + } + return this.getRun( matching[ 0 ].id ); + } + + getRelease() { + return this.request( + `/repos/${ this.repository }/releases/tags/${ RELEASE_TAG }`, + { allowNotFound: true } + ); + } + + createRelease() { + return this.request( `/repos/${ this.repository }/releases`, { + method: 'POST', + json: { + tag_name: RELEASE_TAG, + name: 'Code Reference Playground previews', + body: 'Automated prerelease for Code Reference Playground snapshots.', + prerelease: true, + }, + } ); + } + + listReleaseAssets( releaseId ) { + return this.pages( + `/repos/${ this.repository }/releases/${ releaseId }/assets` + ); + } + + uploadReleaseAsset( releaseId, name, bytes, contentType ) { + return this.request( + `${ UPLOADS }/repos/${ + this.repository + }/releases/${ releaseId }/assets?${ query( { name } ) }`, + { + method: 'POST', + headers: { + Accept: 'application/vnd.github+json', + 'Content-Type': contentType, + }, + body: bytes, + } + ); + } + + deleteReleaseAsset( assetId ) { + return this.request( + `/repos/${ this.repository }/releases/assets/${ assetId }`, + { method: 'DELETE' } + ); + } + + async findPreviewComment( pullRequestNumber ) { + const comments = await this.pages( + `/repos/${ this.repository }/issues/${ pullRequestNumber }/comments` + ); + return ( + comments.find( + ( comment ) => + comment.user?.type === 'Bot' && + comment.body.includes( COMMENT_MARKER ) + ) || null + ); + } + + createComment( pullRequestNumber, body ) { + return this.request( + `/repos/${ this.repository }/issues/${ pullRequestNumber }/comments`, + { method: 'POST', json: { body } } + ); + } + + updateComment( commentId, body ) { + return this.request( + `/repos/${ this.repository }/issues/comments/${ commentId }`, + { method: 'PATCH', json: { body } } + ); + } + + removeLabel( pullRequestNumber ) { + return this.request( + `/repos/${ this.repository }/issues/${ pullRequestNumber }/labels/docs-preview`, + { method: 'DELETE', allowNotFound: true } + ); + } +} diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs new file mode 100644 index 0000000000000..052c0da77b65d --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -0,0 +1,165 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; + +import { GitHubApi } from '../lib/github.mjs'; +import { COMMENT_MARKER, RELEASE_TAG } from '../lib/publication.mjs'; + +function response( value, status = 200 ) { + return { + ok: status >= 200 && status < 300, + status, + json: async () => value, + text: async () => JSON.stringify( value ), + }; +} + +function run( overrides = {} ) { + return { + id: 456, + run_attempt: 1, + head_sha: 'a'.repeat( 40 ), + head_branch: 'feature', + head_repository: { + full_name: 'contributor/wordpress-develop', + owner: { login: 'contributor' }, + }, + ...overrides, + }; +} + +function pullRequest( overrides = {} ) { + return { + number: 123, + base: { ref: 'trunk' }, + head: { + sha: 'a'.repeat( 40 ), + ref: 'feature', + repo: { full_name: 'contributor/wordpress-develop' }, + }, + ...overrides, + }; +} + +test( 'API requests use the repository token and report failures', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + calls.push( { url, options } ); + return response( { id: 456 } ); + } + ); + assert.equal( ( await api.getRun( 456 ) ).id, 456 ); + assert.match( calls[ 0 ].url, /actions\/runs\/456$/ ); + assert.equal( calls[ 0 ].options.headers.Authorization, 'Bearer token' ); + + const failing = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async () => response( { message: 'no' }, 403 ) + ); + await assert.rejects( failing.getRun( 456 ), /HTTP 403/ ); +} ); + +test( 'a fork run resolves its PR without workflow pull_requests data', async () => { + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + assert.match( url, /state=open/ ); + assert.match( url, /head=contributor%3Afeature/ ); + return response( [ pullRequest() ] ); + } + ); + assert.equal( ( await api.findPullRequestForRun( run() ) ).number, 123 ); + + const ambiguous = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async () => + response( [ pullRequest(), pullRequest( { number: 124 } ) ] ) + ); + await assert.rejects( + ambiguous.findPullRequestForRun( run() ), + /Expected one pull request/ + ); +} ); + +test( 'latest run lookup binds SHA, branch, repository, and current attempt', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + calls.push( url ); + if ( url.includes( '/actions/workflows/' ) ) { + return response( { + workflow_runs: [ + run( { id: 789, head_branch: 'other' } ), + run( { id: 456 } ), + ], + } ); + } + return response( run( { id: 456, run_attempt: 2 } ) ); + } + ); + const latest = await api.latestPreviewRun( run() ); + assert.equal( latest.run_attempt, 2 ); + assert.match( calls[ 0 ], /head_sha=/ ); + assert.match( calls[ 1 ], /actions\/runs\/456$/ ); +} ); + +test( 'release operations keep immutable names and bytes', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + calls.push( { url, options } ); + if ( options.method === 'DELETE' ) { + return response( null, 204 ); + } + return response( { id: 9, name: 'snapshot.zip' } ); + } + ); + await api.createRelease(); + await api.uploadReleaseAsset( + 9, + 'snapshot.zip', + Buffer.from( 'snapshot' ), + 'application/zip' + ); + await api.deleteReleaseAsset( 10 ); + assert.equal( calls[ 0 ].options.json.tag_name, RELEASE_TAG ); + assert.match( calls[ 1 ].url, /^https:\/\/uploads\.github\.com/ ); + assert.equal( calls[ 1 ].options.body.toString(), 'snapshot' ); + assert.equal( calls[ 2 ].options.method, 'DELETE' ); +} ); + +test( 'only the marked bot comment is updated', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + calls.push( { url, options } ); + if ( url.includes( '/comments?per_page' ) ) { + return response( [ + { id: 1, user: { type: 'User' }, body: COMMENT_MARKER }, + { id: 2, user: { type: 'Bot' }, body: COMMENT_MARKER }, + ] ); + } + if ( options.method === 'DELETE' ) { + return response( null, 204 ); + } + return response( { id: 2 } ); + } + ); + assert.equal( ( await api.findPreviewComment( 123 ) ).id, 2 ); + await api.updateComment( 2, 'updated' ); + await api.removeLabel( 123 ); + assert.equal( calls[ 1 ].options.method, 'PATCH' ); + assert.deepEqual( calls[ 1 ].options.json, { body: 'updated' } ); + assert.match( calls[ 2 ].url, /labels\/docs-preview$/ ); +} ); From 02c2cd2ba7b657a0504fe5297691d5642ffb8192 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:37:51 +0400 Subject: [PATCH 14/59] Build/Test Tools: Add published preview validation A release upload is not a usable preview until the public path returns the expected bytes. Validate the public metadata, launch pointer, proxy headers, size, and digest before accepting it. Obsolete fork runs exit without touching current state. Previous-preview discovery fetches accepted metadata twice. That is redundant network work, not a correctness defect. --- .../docs-playground-preview/lib/github.mjs | 3 + .../docs-playground-preview/lib/published.mjs | 132 +++++++++++ .../test/github.test.mjs | 6 + .../test/published.test.mjs | 220 ++++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lib/published.mjs create mode 100644 .github/scripts/docs-playground-preview/test/published.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index cb104e84bd421..a186c75d9400e 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -99,6 +99,9 @@ export class GitHubApi { pullRequest.head.repo?.full_name === run.head_repository.full_name ); + if ( matches.length === 0 ) { + return null; + } if ( matches.length !== 1 ) { throw new Error( `Expected one pull request for the workflow run; found ${ matches.length }.` diff --git a/.github/scripts/docs-playground-preview/lib/published.mjs b/.github/scripts/docs-playground-preview/lib/published.mjs new file mode 100644 index 0000000000000..99e9750fc26b8 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/published.mjs @@ -0,0 +1,132 @@ +import { SNAPSHOT_BYTES_LIMIT } from './publisher.mjs'; +import { + corsProxyUrl, + metadataAssetName, + playgroundUrl, + releaseAssetUrl, + validatePublicSnapshot, + validateReusableMetadata, +} from './publication.mjs'; + +const BLUEPRINT_SCHEMA = + 'https://playground.wordpress.net/blueprint-schema.json'; + +async function fetchPublishedMetadata( asset, fetchImplementation ) { + const response = await fetchImplementation( asset.browser_download_url ); + if ( response.status !== 200 ) { + throw new Error( + `Public metadata returned HTTP ${ response.status }.` + ); + } + return response.json(); +} + +function validatePublishedFields( metadata, repository, snapshotAsset ) { + const snapshotUrl = releaseAssetUrl( repository, snapshotAsset.name ); + if ( + snapshotAsset.browser_download_url !== snapshotUrl || + metadata.publication?.snapshotUrl !== snapshotUrl || + metadata.publication?.snapshotProxyUrl !== + corsProxyUrl( snapshotUrl ) || + metadata.publication?.playgroundUrl !== + playgroundUrl( snapshotUrl, { + blueprintSchema: BLUEPRINT_SCHEMA, + phpVersion: metadata.phpVersion, + wordpressVersion: metadata.resolvedWordPressBeta.version, + } ) || + typeof metadata.publication?.publishedAt !== 'string' || + ! metadata.publication.publishedAt.endsWith( 'Z' ) || + Number.isNaN( Date.parse( metadata.publication.publishedAt ) ) + ) { + throw new Error( 'Published preview pointer metadata is invalid.' ); + } +} + +export async function loadPublishedPreview( + repository, + pullRequestNumber, + metadataAsset, + snapshotAsset, + options +) { + const metadata = validateReusableMetadata( + await fetchPublishedMetadata( + metadataAsset, + options.fetchImplementation + ), + { + sourceRepository: options.sourceRepository, + pullRequestNumber, + sourceSha: options.sourceSha, + maximumBytes: SNAPSHOT_BYTES_LIMIT, + } + ); + if ( + metadataAsset.name !== metadataAssetName( metadata.snapshotFilename ) || + snapshotAsset.name !== metadata.snapshotFilename + ) { + throw new Error( 'Published release asset names are invalid.' ); + } + validatePublishedFields( metadata, repository, snapshotAsset ); + await validatePublicSnapshot( + snapshotAsset.browser_download_url, + { + bytes: metadata.snapshotBytes, + sha256: metadata.snapshotSha256, + maximumBytes: SNAPSHOT_BYTES_LIMIT, + }, + options.fetchImplementation + ); + return metadata; +} + +export async function findPreviousPreview( session, excluded = new Set() ) { + const release = await session.api.getRelease(); + if ( ! release ) { + return null; + } + const assets = await session.api.listReleaseAssets( release.id ); + const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; + const candidates = assets + .filter( + ( asset ) => + asset.name.startsWith( prefix ) && + asset.name.endsWith( '.json' ) && + ! excluded.has( asset.name ) + ) + .sort( ( left, right ) => + right.created_at.localeCompare( left.created_at ) + ); + for ( const metadataAsset of candidates ) { + try { + const published = await fetchPublishedMetadata( + metadataAsset, + session.fetchImplementation + ); + const snapshotAsset = assets.find( + ( asset ) => + asset.name === published.snapshotFilename && + ! excluded.has( asset.name ) + ); + if ( ! snapshotAsset ) { + throw new Error( 'Published snapshot asset is missing.' ); + } + return await loadPublishedPreview( + session.repository, + session.context.pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository: published.sourceRepository, + sourceSha: published.sourceSha, + fetchImplementation: session.fetchImplementation, + } + ); + } catch ( error ) { + session.warning( + `Cannot retain ${ metadataAsset.name }: ${ error.message }` + ); + } + } + return null; +} diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index 052c0da77b65d..abbbfbefd9013 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -73,6 +73,12 @@ test( 'a fork run resolves its PR without workflow pull_requests data', async () } ); assert.equal( ( await api.findPullRequestForRun( run() ) ).number, 123 ); + const obsolete = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async () => response( [] ) + ); + assert.equal( await obsolete.findPullRequestForRun( run() ), null ); const ambiguous = new GitHubApi( 'WordPress/wordpress-develop', diff --git a/.github/scripts/docs-playground-preview/test/published.test.mjs b/.github/scripts/docs-playground-preview/test/published.test.mjs new file mode 100644 index 0000000000000..2f094e9fcfdd1 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/published.test.mjs @@ -0,0 +1,220 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { test } from 'node:test'; + +import { + findPreviousPreview, + loadPublishedPreview, +} from '../lib/published.mjs'; +import { + PLAYGROUND_ORIGIN, + corsProxyUrl, + metadataAssetName, + playgroundUrl, + releaseAssetUrl, + snapshotAssetName, +} from '../lib/publication.mjs'; + +const repository = 'WordPress/wordpress-develop'; +const sourceRepository = 'contributor/wordpress-develop'; +const pullRequestNumber = 123; +const sourceSha = 'a'.repeat( 40 ); +const bytes = Buffer.from( 'snapshot' ); + +function published() { + const snapshotFilename = snapshotAssetName( { + pullRequestNumber, + sourceSha, + workflowRunId: 456, + workflowRunAttempt: 1, + } ); + const snapshotUrl = releaseAssetUrl( repository, snapshotFilename ); + return { + schemaVersion: 1, + sourceRepository, + pullRequestNumber, + sourceSha, + workflowRunId: '456', + workflowRunAttempt: 1, + runUrl: `https://github.com/${ repository }/actions/runs/456`, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename, + snapshotBytes: bytes.byteLength, + snapshotSha256: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + generationTimestamp: '2026-08-09T12:34:56.000Z', + publication: { + snapshotUrl, + snapshotProxyUrl: corsProxyUrl( snapshotUrl ), + playgroundUrl: playgroundUrl( snapshotUrl, { + blueprintSchema: + 'https://playground.wordpress.net/blueprint-schema.json', + phpVersion: '8.4', + wordpressVersion: '7.2-beta1', + } ), + publishedAt: '2026-08-09T12:35:00.000Z', + }, + }; +} + +function assets( metadata ) { + return { + metadataAsset: { + name: metadataAssetName( metadata.snapshotFilename ), + browser_download_url: `https://github.com/metadata/${ metadata.snapshotFilename }.json`, + created_at: '2026-08-09T12:35:00Z', + }, + snapshotAsset: { + name: metadata.snapshotFilename, + browser_download_url: releaseAssetUrl( + repository, + metadata.snapshotFilename + ), + created_at: '2026-08-09T12:34:59Z', + }, + }; +} + +function headers() { + return { + get: ( name ) => + ( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } )[ name.toLowerCase() ] || null, + }; +} + +function publicFetch( metadata, metadataAsset ) { + return async ( url ) => { + if ( url === metadataAsset.browser_download_url ) { + return { status: 200, json: async () => metadata }; + } + assert.equal( url, metadata.publication.snapshotProxyUrl ); + return { + status: 200, + headers: headers(), + arrayBuffer: async () => bytes, + }; + }; +} + +test( 'a published preview is accepted only through its public delivery path', async () => { + const metadata = published(); + const { metadataAsset, snapshotAsset } = assets( metadata ); + assert.equal( + await loadPublishedPreview( + repository, + pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository, + sourceSha, + fetchImplementation: publicFetch( metadata, metadataAsset ), + } + ), + metadata + ); +} ); + +test( 'a published preview rejects invalid pointer identity and proxy bytes', async () => { + const metadata = published(); + const { metadataAsset, snapshotAsset } = assets( metadata ); + await assert.rejects( + loadPublishedPreview( + repository, + pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository, + sourceSha, + fetchImplementation: publicFetch( + { + ...metadata, + publication: { + ...metadata.publication, + publishedAt: '2026-08-09T12:35:00+04:00', + }, + }, + metadataAsset + ), + } + ), + /pointer metadata/ + ); + + await assert.rejects( + loadPublishedPreview( + repository, + pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository, + sourceSha, + fetchImplementation: async ( url ) => { + if ( url === metadataAsset.browser_download_url ) { + return { status: 200, json: async () => metadata }; + } + return { + status: 200, + headers: headers(), + arrayBuffer: async () => Buffer.from( 'changed' ), + }; + }, + } + ), + /bytes/ + ); +} ); + +test( 'previous-preview discovery skips broken and excluded assets', async () => { + const metadata = published(); + const { metadataAsset, snapshotAsset } = assets( metadata ); + const broken = { + name: `code-reference-pr-${ pullRequestNumber }-${ 'c'.repeat( + 40 + ) }-999-1.json`, + browser_download_url: 'https://github.com/metadata/broken.json', + created_at: '2026-08-09T12:36:00Z', + }; + const warnings = []; + const session = { + repository, + context: { pullRequestNumber }, + warning: ( message ) => warnings.push( message ), + fetchImplementation: async ( url ) => { + if ( url === broken.browser_download_url ) { + return { status: 404 }; + } + return publicFetch( metadata, metadataAsset )( url ); + }, + api: { + getRelease: async () => ( { id: 1 } ), + listReleaseAssets: async () => [ + broken, + metadataAsset, + snapshotAsset, + ], + }, + }; + assert.equal( await findPreviousPreview( session ), metadata ); + assert.equal( warnings.length, 1 ); + assert.equal( + await findPreviousPreview( + session, + new Set( [ metadataAsset.name, snapshotAsset.name ] ) + ), + null + ); +} ); From 02155ccf68b547dc6bcafdae307bca5993a90417 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:46:44 +0400 Subject: [PATCH 15/59] Build/Test Tools: Publish PR snapshots transactionally Publication is the privileged boundary. Recheck the current head before every mutation, validate public delivery before moving the comment, and upload before deleting the old preview. Failed cleanup touches only asset IDs uploaded by this invocation. Comment, cleanup, and label failures remain visible instead of masquerading as supersession. --- .../docs-playground-preview/publish.mjs | 376 ++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/publish.mjs diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs new file mode 100644 index 0000000000000..ef24ae6f29a9b --- /dev/null +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -0,0 +1,376 @@ +#!/usr/bin/env node + +import { readFile } from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; +import path from 'node:path'; + +import { GitHubApi } from './lib/github.mjs'; +import { + assertLatestAuthorized, + createPublishedMetadata, + inspectHandoff, + renderPreviewComment, + validateCandidateFile, + validatePublicationContext, +} from './lib/publisher.mjs'; +import { metadataAssetName } from './lib/publication.mjs'; +import { findPreviousPreview, loadPublishedPreview } from './lib/published.mjs'; + +class SupersededRun extends Error {} + +async function readHandoff( directory ) { + return JSON.parse( + await readFile( path.join( directory, 'build.json' ), 'utf8' ) + ); +} + +async function establishSession( options ) { + const api = + options.api || + new GitHubApi( + options.repository, + options.token, + options.fetchImplementation + ); + const run = await api.getRun( options.triggerRunId ); + const pullRequest = await api.findPullRequestForRun( run ); + if ( ! pullRequest ) { + return null; + } + const base = { + repository: options.repository, + stagingVariable: options.stagingVariable, + triggerRunId: options.triggerRunId, + triggerRunAttempt: options.triggerRunAttempt, + run, + pullRequest, + }; + const context = validatePublicationContext( base ); + return { + api, + context, + repository: options.repository, + fetchImplementation: options.fetchImplementation || globalThis.fetch, + warning: options.warning || console.warn, + now: options.now || ( () => new Date().toISOString() ), + handoffDirectory: path.resolve( options.handoffDirectory ), + authorize: async () => { + const currentRun = await api.getRun( options.triggerRunId ); + const currentPullRequest = await api.getPullRequest( + context.pullRequestNumber + ); + const latestRun = await api.latestPreviewRun( currentRun ); + try { + return assertLatestAuthorized( { + ...base, + run: currentRun, + pullRequest: currentPullRequest, + latestRun, + } ); + } catch ( error ) { + throw new SupersededRun( error.message ); + } + }, + }; +} + +async function ensureRelease( session ) { + let release = await session.api.getRelease(); + if ( release ) { + return release; + } + await session.authorize(); + try { + release = await session.api.createRelease(); + } catch ( error ) { + release = await session.api.getRelease(); + if ( ! release ) { + throw error; + } + } + return release; +} + +async function upsertComment( session, body ) { + const comment = await session.api.findPreviewComment( + session.context.pullRequestNumber + ); + await session.authorize(); + if ( comment ) { + await session.api.updateComment( comment.id, body ); + } else { + await session.api.createComment( + session.context.pullRequestNumber, + body + ); + } +} + +async function removeRequestLabel( session ) { + await session.authorize(); + await session.api.removeLabel( session.context.pullRequestNumber ); +} + +async function cleanupOldAssets( session, assets, keep ) { + const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; + for ( const asset of assets ) { + if ( asset.name.startsWith( prefix ) && ! keep.has( asset.name ) ) { + await session.authorize(); + await session.api.deleteReleaseAsset( asset.id ); + } + } +} + +async function cleanupFailedCandidate( session, assets ) { + for ( const asset of assets ) { + await session.authorize(); + await session.api.deleteReleaseAsset( asset.id ); + } +} + +async function runIndependently( operations, message ) { + const errors = []; + for ( const operation of operations ) { + try { + await operation(); + } catch ( error ) { + errors.push( error ); + } + } + if ( + errors.length === 1 || + ( errors.length > 1 && + errors.every( ( error ) => error instanceof SupersededRun ) ) + ) { + throw errors[ 0 ]; + } + if ( errors.length > 1 ) { + throw new AggregateError( errors, message ); + } +} + +async function reportFailure( session, excluded = new Set() ) { + const previous = await findPreviousPreview( session, excluded ); + const body = renderPreviewComment( { + status: 'failed', + sourceRepository: session.context.sourceRepository, + sourceSha: session.context.sourceSha, + at: session.now(), + runUrl: session.context.runUrl, + previous, + } ); + await runIndependently( + [ + () => upsertComment( session, body ), + () => removeRequestLabel( session ), + ], + 'Failure comment and label removal both failed.' + ); +} + +async function finishReady( session, assets, keep ) { + try { + await runIndependently( + [ + () => cleanupOldAssets( session, assets, keep ), + () => removeRequestLabel( session ), + ], + 'Old-asset cleanup and label removal both failed.' + ); + } catch ( error ) { + error.preserveReadyComment = true; + throw error; + } +} + +async function publishCandidate( session, metadata, uploadedAssets ) { + const candidateFile = path.join( + session.handoffDirectory, + metadata.snapshotFilename + ); + await validateCandidateFile( metadata, candidateFile ); + const release = await ensureRelease( session ); + const oldAssets = await session.api.listReleaseAssets( release.id ); + const snapshotBytes = await readFile( candidateFile ); + await session.authorize(); + const snapshotAsset = await session.api.uploadReleaseAsset( + release.id, + metadata.snapshotFilename, + snapshotBytes, + 'application/zip' + ); + uploadedAssets.push( snapshotAsset ); + const published = createPublishedMetadata( + metadata, + session.repository, + session.now() + ); + const publishedBytes = Buffer.from( + `${ JSON.stringify( published, null, 2 ) }\n` + ); + await session.authorize(); + const metadataAsset = await session.api.uploadReleaseAsset( + release.id, + metadataAssetName( metadata.snapshotFilename ), + publishedBytes, + 'application/json' + ); + uploadedAssets.push( metadataAsset ); + const preview = await loadPublishedPreview( + session.repository, + session.context.pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository: session.context.sourceRepository, + sourceSha: session.context.sourceSha, + fetchImplementation: session.fetchImplementation, + } + ); + await upsertComment( + session, + renderPreviewComment( { + status: 'ready', + preview, + runUrl: session.context.runUrl, + } ) + ); + const keep = new Set( [ snapshotAsset.name, metadataAsset.name ] ); + await finishReady( session, oldAssets, keep ); + return { status: 'ready', preview }; +} + +async function reuseCandidate( session, metadata ) { + const release = await session.api.getRelease(); + if ( ! release ) { + throw new Error( 'Reusable release is missing.' ); + } + const assets = await session.api.listReleaseAssets( release.id ); + const snapshotAsset = assets.find( + ( asset ) => asset.name === metadata.reusedSnapshot.assetName + ); + const metadataAsset = assets.find( + ( asset ) => asset.name === metadata.reusedSnapshot.metadataAssetName + ); + if ( ! snapshotAsset || ! metadataAsset ) { + throw new Error( 'Reusable release assets are missing.' ); + } + const preview = await loadPublishedPreview( + session.repository, + session.context.pullRequestNumber, + metadataAsset, + snapshotAsset, + { + sourceRepository: session.context.sourceRepository, + sourceSha: session.context.sourceSha, + fetchImplementation: session.fetchImplementation, + } + ); + for ( const name of [ + 'snapshotFilename', + 'snapshotBytes', + 'snapshotSha256', + 'generationTimestamp', + 'dependencyManifestDigest', + ] ) { + if ( preview[ name ] !== metadata[ name ] ) { + throw new Error( + `Reusable ${ name } does not match public metadata.` + ); + } + } + await upsertComment( + session, + renderPreviewComment( { + status: 'ready', + preview, + runUrl: session.context.runUrl, + } ) + ); + await finishReady( + session, + assets, + new Set( [ snapshotAsset.name, metadataAsset.name ] ) + ); + return { status: 'reused', preview }; +} + +export async function publishPullRequest( options ) { + const session = await establishSession( options ); + if ( ! session ) { + return { status: 'superseded' }; + } + const uploadedAssets = []; + try { + await session.authorize(); + if ( options.artifactAvailable === false ) { + throw new Error( 'The publisher handoff artifact is unavailable.' ); + } + const metadata = await readHandoff( session.handoffDirectory ); + const handoff = inspectHandoff( metadata, { + ...session.context, + latestRun: session.context.run, + } ); + if ( handoff.kind === 'failed' ) { + throw new Error( metadata.buildError || 'Preview build failed.' ); + } + if ( handoff.kind === 'invalid' ) { + await reportFailure( session ); + return { status: 'invalid' }; + } + if ( handoff.kind === 'reuse' ) { + return await reuseCandidate( session, metadata ); + } + return await publishCandidate( session, metadata, uploadedAssets ); + } catch ( error ) { + if ( error instanceof SupersededRun ) { + return { status: 'superseded' }; + } + if ( error.preserveReadyComment ) { + throw error; + } + const excluded = new Set( + uploadedAssets.map( ( asset ) => asset.name ) + ); + try { + await cleanupFailedCandidate( session, uploadedAssets ); + } catch ( cleanupError ) { + session.warning( + `Cannot remove failed candidate: ${ cleanupError.message }` + ); + } + try { + await reportFailure( session, excluded ); + } catch ( reportError ) { + if ( reportError instanceof SupersededRun ) { + return { status: 'superseded' }; + } + throw new AggregateError( + [ error, reportError ], + 'Publication and failure reporting both failed.' + ); + } + throw error; + } +} + +async function main() { + const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const result = await publishPullRequest( { + repository: process.env.GITHUB_REPOSITORY, + stagingVariable: process.env.DOCS_PREVIEW_STAGING, + triggerRunId: event.workflow_run.id, + triggerRunAttempt: event.workflow_run.run_attempt, + handoffDirectory: process.argv[ 2 ] || 'handoff', + artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', + token: process.env.GITHUB_TOKEN, + } ); + console.log( `Code Reference publisher: ${ result.status }.` ); +} + +if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { + main().catch( ( error ) => { + console.error( error ); + process.exitCode = 1; + } ); +} From d2a18d618417266b8bf7c9e72ba42e4ea4d59511 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:47:46 +0400 Subject: [PATCH 16/59] Build/Test Tools: Test PR publication transactions Publication failures must not erase the last working preview or leave the request label stuck behind unrelated cleanup. Exercise fresh publication, advisory failure, missing artifacts, latest-wins, retry collisions, public delivery failure, reuse, and ordinary transport errors. Mutation ordering is inferred from final state and injected failures rather than a separate operation log. The product boundary is still covered. --- .../test/publish.test.mjs | 450 ++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/test/publish.test.mjs diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs new file mode 100644 index 0000000000000..f68fa13c3cf79 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -0,0 +1,450 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { mkdtemp, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { createPublishedMetadata } from '../lib/publisher.mjs'; +import { + PLAYGROUND_ORIGIN, + createReuseHandoff, + metadataAssetName, + releaseAssetUrl, + snapshotAssetName, +} from '../lib/publication.mjs'; +import { publishPullRequest } from '../publish.mjs'; + +const repository = 'WordPress/wordpress-develop'; +const sourceRepository = 'contributor/wordpress-develop'; +const sha = 'a'.repeat( 40 ); +const snapshotBytes = Buffer.from( 'snapshot' ); + +function run() { + return { + id: 456, + run_attempt: 1, + name: 'Code Reference Playground Preview Build', + event: 'pull_request', + status: 'completed', + head_sha: sha, + head_branch: 'feature', + head_repository: { + full_name: sourceRepository, + owner: { login: 'contributor' }, + }, + }; +} + +function pullRequest() { + return { + number: 123, + state: 'open', + base: { ref: 'trunk' }, + head: { + sha, + ref: 'feature', + repo: { full_name: sourceRepository }, + }, + labels: [ { name: 'docs-preview' } ], + }; +} + +function buildMetadata( overrides = {} ) { + const identity = { + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: 456, + workflowRunAttempt: 1, + }; + return { + schemaVersion: 1, + sourceRepository, + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: '456', + workflowRunAttempt: 1, + runUrl: `${ + releaseAssetUrl( repository, 'x' ).split( '/releases/' )[ 0 ] + }/actions/runs/456`, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename: snapshotAssetName( identity ), + snapshotBytes: snapshotBytes.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( snapshotBytes ) + .digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + validationFailures: [], + generationTimestamp: '2026-08-09T12:34:56.000Z', + ...overrides, + }; +} + +function releaseAsset( id, name, createdAt = '2026-08-08T13:00:00.000Z' ) { + return { + id, + name, + created_at: createdAt, + browser_download_url: releaseAssetUrl( repository, name ), + }; +} + +class FakeApi { + constructor() { + this.currentRun = run(); + this.currentPullRequest = pullRequest(); + this.latestRun = this.currentRun; + this.release = { id: 9 }; + this.assets = []; + this.metadata = new Map(); + this.assetBytes = new Map(); + this.uploads = []; + this.deleted = []; + this.comments = []; + this.labelRemovals = 0; + this.runReads = 0; + this.deleteError = null; + this.uploadError = null; + } + + async getRun() { + this.runReads++; + return this.currentRun; + } + + async findPullRequestForRun() { + return this.currentPullRequest; + } + + async getPullRequest() { + return this.currentPullRequest; + } + + async latestPreviewRun() { + return this.latestRun; + } + + async getRelease() { + return this.release; + } + + async createRelease() { + this.release = { id: 9 }; + return this.release; + } + + async listReleaseAssets() { + return [ ...this.assets ]; + } + + async uploadReleaseAsset( releaseId, name, bytes, contentType ) { + assert.equal( releaseId, 9 ); + if ( this.uploadError ) { + throw this.uploadError; + } + const asset = { + id: this.assets.length + 10, + name, + created_at: '2026-08-09T13:00:00.000Z', + browser_download_url: releaseAssetUrl( repository, name ), + }; + this.assets.push( asset ); + this.uploads.push( { name, contentType } ); + if ( contentType === 'application/json' ) { + this.metadata.set( name, JSON.parse( bytes.toString() ) ); + } else { + this.assetBytes.set( name, Buffer.from( bytes ) ); + } + return asset; + } + + async deleteReleaseAsset( id ) { + if ( this.deleteError ) { + throw this.deleteError; + } + this.deleted.push( id ); + } + + async findPreviewComment() { + return this.comments[ 0 ] || null; + } + + async createComment( number, body ) { + this.comments = [ { id: 1, number, body } ]; + } + + async updateComment( id, body ) { + this.comments = [ { id, body } ]; + } + + async removeLabel() { + this.labelRemovals++; + } +} + +function publicFetch( api, corrupt = new Set() ) { + return async ( url ) => { + if ( url.includes( 'wordpress-playground-cors-proxy.net' ) ) { + const name = url.split( '/' ).at( -1 ); + const bytes = corrupt.has( name ) + ? Buffer.from( 'corrupt!' ) + : api.assetBytes.get( name ); + return { + status: 200, + headers: { + get: ( header ) => + ( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } )[ header.toLowerCase() ] || null, + }, + arrayBuffer: async () => bytes, + }; + } + const name = url.split( '/' ).at( -1 ); + return { + status: api.metadata.has( name ) ? 200 : 404, + json: async () => api.metadata.get( name ), + }; + }; +} + +async function handoffDirectory( metadata, includeSnapshot = true ) { + const directory = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-publish-' ) + ); + await writeFile( + path.join( directory, 'build.json' ), + `${ JSON.stringify( metadata ) }\n` + ); + if ( includeSnapshot ) { + await writeFile( + path.join( directory, metadata.snapshotFilename ), + snapshotBytes + ); + } + return directory; +} + +function options( api, directory, extra = {} ) { + return { + repository, + stagingVariable: '', + triggerRunId: 456, + triggerRunAttempt: 1, + handoffDirectory: directory, + artifactAvailable: true, + api, + fetchImplementation: publicFetch( api ), + now: () => '2026-08-09T13:00:00.000Z', + warning: () => {}, + ...extra, + }; +} + +function installPublishedPreview( + api, + build, + content = snapshotBytes, + publishedAt = '2026-08-08T13:00:00.000Z' +) { + const published = createPublishedMetadata( build, repository, publishedAt ); + const metadataName = metadataAssetName( build.snapshotFilename ); + api.assets.push( + releaseAsset( 1, build.snapshotFilename, publishedAt ), + releaseAsset( 2, metadataName, publishedAt ) + ); + api.metadata.set( metadataName, published ); + api.assetBytes.set( build.snapshotFilename, content ); + return published; +} + +test( 'a candidate is public before the comment moves and old assets delete', async () => { + const api = new FakeApi(); + const metadata = buildMetadata(); + const directory = await handoffDirectory( metadata ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'ready' ); + assert.deepEqual( + api.uploads.map( ( upload ) => upload.contentType ), + [ 'application/zip', 'application/json' ] + ); + assert.match( api.comments[ 0 ].body, /Status:\*\* Ready/ ); + assert.match( api.comments[ 0 ].body, /blueprint-url=/ ); + assert.equal( api.labelRemovals, 1 ); + assert.ok( api.runReads >= 5 ); +} ); + +test( 'an advisory validation failure updates the comment but publishes nothing', async () => { + const api = new FakeApi(); + const metadata = buildMetadata( { validationStatus: 'failed' } ); + const directory = await handoffDirectory( metadata, false ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'invalid' ); + assert.equal( api.uploads.length, 0 ); + assert.match( api.comments[ 0 ].body, /Latest attempt failed/ ); + assert.equal( api.labelRemovals, 1 ); +} ); + +test( 'a missing handoff always fails after its terminal comment', async () => { + const api = new FakeApi(); + const directory = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-missing-' ) + ); + await assert.rejects( + publishPullRequest( + options( api, directory, { artifactAvailable: false } ) + ), + /artifact is unavailable/ + ); + assert.match( api.comments[ 0 ].body, /Latest attempt failed/ ); + assert.equal( api.labelRemovals, 1 ); +} ); + +test( 'a superseded run makes no mutation', async () => { + const api = new FakeApi(); + api.latestRun = { ...api.currentRun, id: 789 }; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'superseded' ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); + assert.equal( api.labelRemovals, 0 ); +} ); + +test( 'public delivery failure keeps the previous healthy preview', async () => { + const api = new FakeApi(); + const oldBytes = Buffer.from( 'old snapshot' ); + const oldBuild = buildMetadata( { + sourceSha: 'c'.repeat( 40 ), + workflowRunId: '300', + snapshotFilename: snapshotAssetName( { + pullRequestNumber: 123, + sourceSha: 'c'.repeat( 40 ), + workflowRunId: 300, + workflowRunAttempt: 1, + } ), + snapshotBytes: oldBytes.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( oldBytes ) + .digest( 'hex' ), + } ); + installPublishedPreview( api, oldBuild, oldBytes ); + + const current = buildMetadata(); + const directory = await handoffDirectory( current ); + await assert.rejects( + publishPullRequest( + options( api, directory, { + fetchImplementation: publicFetch( + api, + new Set( [ current.snapshotFilename ] ) + ), + } ) + ), + /digest/ + ); + assert.deepEqual( + api.deleted.sort( ( left, right ) => left - right ), + [ 12, 13 ] + ); + assert.match( api.comments[ 0 ].body, /Latest successful docs preview/ ); + assert.match( api.comments[ 0 ].body, new RegExp( 'c'.repeat( 40 ) ) ); +} ); + +test( 'a retry cannot delete a same-name preview it did not upload', async () => { + const api = new FakeApi(); + const current = buildMetadata(); + installPublishedPreview( api, current ); + api.uploadError = new Error( 'already_exists' ); + const directory = await handoffDirectory( current ); + await assert.rejects( + publishPullRequest( options( api, directory ) ), + /already_exists/ + ); + assert.deepEqual( api.deleted, [] ); + assert.match( api.comments[ 0 ].body, /Latest successful docs preview/ ); +} ); + +test( 'a healthy same-SHA preview is reused without uploading it again', async () => { + const api = new FakeApi(); + const oldBuild = buildMetadata( { + workflowRunId: '300', + workflowRunAttempt: 1, + runUrl: `https://github.com/${ repository }/actions/runs/300`, + snapshotFilename: snapshotAssetName( { + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: 300, + workflowRunAttempt: 1, + } ), + } ); + const oldPublished = installPublishedPreview( api, oldBuild ); + api.assets.push( + releaseAsset( + 3, + `code-reference-pr-123-${ 'c'.repeat( 40 ) }-200-1.zip`, + '2026-08-07T13:00:00.000Z' + ) + ); + const handoff = createReuseHandoff( oldPublished, { + sourceRepository, + pullRequestNumber: 123, + sourceSha: sha, + workflowRunId: 456, + workflowRunAttempt: 1, + runUrl: `https://github.com/${ repository }/actions/runs/456`, + maximumBytes: 104857600, + } ); + const directory = await handoffDirectory( handoff, false ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'reused' ); + assert.equal( api.uploads.length, 0 ); + assert.deepEqual( api.deleted, [ 3 ] ); + assert.match( api.comments[ 0 ].body, /Status:\*\* Ready/ ); + assert.equal( api.labelRemovals, 1 ); +} ); + +test( 'cleanup failure cannot replace an already-ready comment', async () => { + const api = new FakeApi(); + api.assets.push( + releaseAsset( + 1, + `code-reference-pr-123-${ 'c'.repeat( 40 ) }-300-1.zip` + ) + ); + api.deleteError = new Error( 'cleanup failed' ); + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishPullRequest( options( api, directory ) ), + /cleanup failed/ + ); + assert.match( api.comments[ 0 ].body, /Status:\*\* Ready/ ); + assert.doesNotMatch( api.comments[ 0 ].body, /Latest attempt failed/ ); + assert.equal( api.labelRemovals, 1 ); +} ); + +test( 'GitHub read failures remain visible publication failures', async () => { + const api = new FakeApi(); + api.getPullRequest = async () => { + throw new Error( 'GitHub is unavailable' ); + }; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishPullRequest( options( api, directory ) ), + ( error ) => { + assert.ok( error instanceof AggregateError ); + assert.match( error.errors[ 0 ].message, /GitHub is unavailable/ ); + return true; + } + ); + assert.equal( api.comments.length, 0 ); +} ); From 7242c105cca63f7defc96d7ec85e808913c59eb0 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:53:39 +0400 Subject: [PATCH 17/59] Build/Test Tools: Publish Code Reference PR snapshots The build job cannot publish with repository authority. Run the publisher from default-branch code, bind the handoff to the exact workflow attempt and pull request, and validate public delivery before moving the sticky comment. GitHub still emits workflow runs when the build job is skipped. Ignore those exact attempts and exclude them from latest-wins selection or an unrelated label consumes the real preview request. --- .../docs-playground-preview/lib/github.mjs | 24 +++++++- .../docs-playground-preview/publish.mjs | 3 + .../test/github.test.mjs | 42 +++++++++++++ .../test/publish.test.mjs | 15 +++++ .../docs-playground-preview-publish.yml | 61 +++++++++++++++++++ 5 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/docs-playground-preview-publish.yml diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index a186c75d9400e..ec9fb544055c2 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -3,6 +3,7 @@ import { COMMENT_MARKER, RELEASE_TAG } from './publication.mjs'; const API = 'https://api.github.com'; const UPLOADS = 'https://uploads.github.com'; const BUILD_WORKFLOW = 'docs-playground-preview-build.yml'; +const BUILD_JOB = 'Build Code Reference snapshot'; function query( values ) { const parameters = new URLSearchParams(); @@ -129,10 +130,27 @@ export class GitHubApi { run.head_repository?.full_name ) .sort( ( left, right ) => right.id - left.id ); - if ( ! matching[ 0 ] ) { - throw new Error( 'No current docs preview run matches this head.' ); + for ( const candidate of matching ) { + const current = await this.getRun( candidate.id ); + if ( ! ( await this.isSkippedPreviewBuild( current ) ) ) { + return current; + } + } + throw new Error( 'No current docs preview build matches this head.' ); + } + + async isSkippedPreviewBuild( run ) { + const jobs = await this.pages( + `/repos/${ this.repository }/actions/runs/${ run.id }/attempts/${ run.run_attempt }/jobs`, + 'jobs' + ); + const matches = jobs.filter( ( job ) => job.name === BUILD_JOB ); + if ( matches.length !== 1 ) { + throw new Error( + `Expected one Code Reference build job; found ${ matches.length }.` + ); } - return this.getRun( matching[ 0 ].id ); + return matches[ 0 ].conclusion === 'skipped'; } getRelease() { diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index ef24ae6f29a9b..1f6529cd2edaa 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -300,6 +300,9 @@ export async function publishPullRequest( options ) { if ( ! session ) { return { status: 'superseded' }; } + if ( await session.api.isSkippedPreviewBuild( session.context.run ) ) { + return { status: 'ignored' }; + } const uploadedAssets = []; try { await session.authorize(); diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index abbbfbefd9013..76aabd956a6b2 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -107,6 +107,16 @@ test( 'latest run lookup binds SHA, branch, repository, and current attempt', as ], } ); } + if ( url.includes( '/jobs?' ) ) { + return response( { + jobs: [ + { + name: 'Build Code Reference snapshot', + conclusion: 'success', + }, + ], + } ); + } return response( run( { id: 456, run_attempt: 2 } ) ); } ); @@ -114,6 +124,38 @@ test( 'latest run lookup binds SHA, branch, repository, and current attempt', as assert.equal( latest.run_attempt, 2 ); assert.match( calls[ 0 ], /head_sha=/ ); assert.match( calls[ 1 ], /actions\/runs\/456$/ ); + assert.match( calls[ 2 ], /runs\/456\/attempts\/2\/jobs/ ); +} ); + +test( 'skipped trigger runs neither publish nor supersede a build', async () => { + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + if ( url.includes( '/actions/workflows/' ) ) { + return response( { + workflow_runs: [ run( { id: 789 } ), run() ], + } ); + } + if ( url.includes( '/jobs?' ) ) { + return response( { + jobs: [ + { + name: 'Build Code Reference snapshot', + conclusion: url.includes( '/789/' ) + ? 'skipped' + : 'success', + }, + ], + } ); + } + return response( + url.endsWith( '/789' ) ? run( { id: 789 } ) : run() + ); + } + ); + assert.equal( ( await api.latestPreviewRun( run() ) ).id, 456 ); + assert.equal( await api.isSkippedPreviewBuild( run( { id: 789 } ) ), true ); } ); test( 'release operations keep immutable names and bytes', async () => { diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index f68fa13c3cf79..db94c1e4c536e 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -132,6 +132,10 @@ class FakeApi { return this.latestRun; } + async isSkippedPreviewBuild() { + return false; + } + async getRelease() { return this.release; } @@ -320,6 +324,17 @@ test( 'a superseded run makes no mutation', async () => { assert.equal( api.labelRemovals, 0 ); } ); +test( 'a skipped trigger run makes no mutation', async () => { + const api = new FakeApi(); + api.isSkippedPreviewBuild = async () => true; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'ignored' ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); + assert.equal( api.labelRemovals, 0 ); +} ); + test( 'public delivery failure keeps the previous healthy preview', async () => { const api = new FakeApi(); const oldBytes = Buffer.from( 'old snapshot' ); diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml new file mode 100644 index 0000000000000..f17070aa916f2 --- /dev/null +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -0,0 +1,61 @@ +name: Code Reference Playground Preview Publish + +on: # zizmor: ignore[dangerous-triggers] Only default-branch code validates and publishes the untrusted handoff. + workflow_run: + workflows: + - 'Code Reference Playground Preview Build' + types: + - completed + +# A fork head branch identifies one trunk pull request even when GitHub omits the +# pull_requests array. Runs queue instead of interrupting a publication halfway. +concurrency: + group: ${{ github.workflow }}-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }} + cancel-in-progress: false + +permissions: {} + +jobs: + publish: + name: Publish Code Reference snapshot + if: >- + github.event.workflow_run.event == 'pull_request' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 30 + permissions: + actions: read + contents: write + issues: write + pull-requests: read + steps: + - name: Check out trusted default-branch publisher code + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Download the exact untrusted handoff + id: download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: docs-preview-handoff-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }} + path: handoff + github-token: ${{ github.token }} + run-id: ${{ github.event.workflow_run.id }} + digest-mismatch: error + + - name: Validate and publish the handoff + env: + DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} + GITHUB_TOKEN: ${{ github.token }} + HANDOFF_DOWNLOAD_RESULT: ${{ steps.download.outcome }} + run: node .github/scripts/docs-playground-preview/publish.mjs handoff From 36f133904ef3fa1e5a3ffc4e90a4b3732a5a8720 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:56:12 +0400 Subject: [PATCH 18/59] Build/Test Tools: Add PR cache cleanup transport Pull request caches live under refs/pull//merge. List that exact scope and delete only returned cache IDs; a broad cache deletion can destroy the shared trunk base. The cache assertions share the release transport test. That is test organization, not a boundary gap. --- .../scripts/docs-playground-preview/lib/github.mjs | 14 ++++++++++++++ .../docs-playground-preview/test/github.test.mjs | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index ec9fb544055c2..916730f808079 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -201,6 +201,20 @@ export class GitHubApi { ); } + listActionCaches( ref ) { + return this.pages( + `/repos/${ this.repository }/actions/caches?${ query( { ref } ) }`, + 'actions_caches' + ); + } + + deleteActionCache( cacheId ) { + return this.request( + `/repos/${ this.repository }/actions/caches/${ cacheId }`, + { method: 'DELETE' } + ); + } + async findPreviewComment( pullRequestNumber ) { const comments = await this.pages( `/repos/${ this.repository }/issues/${ pullRequestNumber }/comments` diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index 76aabd956a6b2..21e6334c53ef7 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -168,6 +168,9 @@ test( 'release operations keep immutable names and bytes', async () => { if ( options.method === 'DELETE' ) { return response( null, 204 ); } + if ( url.includes( '/actions/caches?' ) ) { + return response( { actions_caches: [] } ); + } return response( { id: 9, name: 'snapshot.zip' } ); } ); @@ -179,10 +182,14 @@ test( 'release operations keep immutable names and bytes', async () => { 'application/zip' ); await api.deleteReleaseAsset( 10 ); + await api.listActionCaches( 'refs/pull/123/merge' ); + await api.deleteActionCache( 11 ); assert.equal( calls[ 0 ].options.json.tag_name, RELEASE_TAG ); assert.match( calls[ 1 ].url, /^https:\/\/uploads\.github\.com/ ); assert.equal( calls[ 1 ].options.body.toString(), 'snapshot' ); assert.equal( calls[ 2 ].options.method, 'DELETE' ); + assert.match( calls[ 3 ].url, /ref=refs%2Fpull%2F123%2Fmerge/ ); + assert.equal( calls[ 4 ].options.method, 'DELETE' ); } ); test( 'only the marked bot comment is updated', async () => { From 744e374d7b9000c4f26cdb112bd05b8f521a2018 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:58:42 +0400 Subject: [PATCH 19/59] Build/Test Tools: Manage Code Reference PR lifecycle A new unlabeled commit makes the published preview stale; closing the pull request removes only that PR's release assets and merge-ref docs caches. Recheck the exact head or closed state before every mutation. Do not mark the comment expired until every preview asset is gone. The tests assert final deletion sets rather than a separate ordering log; the transaction order remains explicit in the driver. --- .../docs-playground-preview/lifecycle.mjs | 237 +++++++++++++++ .../test/lifecycle.test.mjs | 271 ++++++++++++++++++ 2 files changed, 508 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/lifecycle.mjs create mode 100644 .github/scripts/docs-playground-preview/test/lifecycle.test.mjs diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs new file mode 100644 index 0000000000000..f5a5dbacd53bb --- /dev/null +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -0,0 +1,237 @@ +#!/usr/bin/env node + +import { readFile } from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; + +import { isDeploymentEnabled } from './lib/config.mjs'; +import { GitHubApi } from './lib/github.mjs'; +import { findPreviousPreview } from './lib/published.mjs'; +import { renderPreviewComment } from './lib/publisher.mjs'; + +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const CACHE_PREFIX = 'docs-preview-base-'; + +class LifecycleSuperseded extends Error {} + +function positiveInteger( value, label ) { + const number = Number( value ); + if ( ! Number.isSafeInteger( number ) || number < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } + return number; +} + +function lifecycleContext( options ) { + if ( + ! isDeploymentEnabled( options.repository, options.stagingVariable ) + ) { + throw new Error( + 'Docs preview lifecycle is disabled in this repository.' + ); + } + const action = options.event?.action; + if ( action !== 'synchronize' && action !== 'closed' ) { + throw new Error( `Unsupported pull request action ${ action }.` ); + } + const pullRequest = options.event.pull_request; + const pullRequestNumber = positiveInteger( + pullRequest?.number, + 'Pull request number' + ); + if ( + pullRequest.base?.ref !== 'trunk' || + ! FULL_COMMIT.test( pullRequest.head?.sha || '' ) + ) { + throw new Error( 'Pull request lifecycle identity is invalid.' ); + } + const sourceRepository = pullRequest.head.repo?.full_name || null; + if ( action === 'synchronize' && ! sourceRepository ) { + throw new Error( 'Open pull request head repository is missing.' ); + } + return { + action, + pullRequestNumber, + sourceRepository, + sourceSha: pullRequest.head.sha, + }; +} + +function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { + if ( + pullRequest.number !== context.pullRequestNumber || + pullRequest.state !== state || + pullRequest.base?.ref !== 'trunk' || + pullRequest.head?.sha !== context.sourceSha || + ( context.sourceRepository && + pullRequest.head.repo?.full_name !== context.sourceRepository ) || + ( labelMustBeAbsent && + pullRequest.labels?.some( + ( label ) => label.name === 'docs-preview' + ) ) + ) { + throw new Error( 'A newer pull request state superseded this event.' ); + } + return pullRequest; +} + +function sessionFrom( options ) { + const context = lifecycleContext( options ); + const api = + options.api || + new GitHubApi( + options.repository, + options.token, + options.fetchImplementation + ); + const authorize = async ( state, labelMustBeAbsent = false ) => { + const pullRequest = await api.getPullRequest( + context.pullRequestNumber + ); + try { + return assertCurrent( + context, + pullRequest, + state, + labelMustBeAbsent + ); + } catch ( error ) { + throw new LifecycleSuperseded( error.message ); + } + }; + return { + api, + context, + repository: options.repository, + fetchImplementation: options.fetchImplementation || globalThis.fetch, + warning: options.warning || console.warn, + authorize, + }; +} + +async function markStale( session ) { + try { + await session.authorize( 'open', true ); + } catch ( error ) { + if ( error instanceof LifecycleSuperseded ) { + return { status: 'ignored' }; + } + throw error; + } + const comment = await session.api.findPreviewComment( + session.context.pullRequestNumber + ); + if ( ! comment ) { + return { status: 'ignored' }; + } + const preview = await findPreviousPreview( session ); + if ( ! preview ) { + return { status: 'unavailable' }; + } + await session.authorize( 'open', true ); + await session.api.updateComment( + comment.id, + renderPreviewComment( { + status: 'stale', + preview, + currentRepository: session.context.sourceRepository, + currentSha: session.context.sourceSha, + } ) + ); + return { status: 'stale' }; +} + +async function settle( operations ) { + const errors = []; + for ( const operation of operations ) { + try { + await operation(); + } catch ( error ) { + errors.push( error ); + } + } + return errors; +} + +async function expire( session ) { + try { + await session.authorize( 'closed' ); + } catch ( error ) { + if ( error instanceof LifecycleSuperseded ) { + return { status: 'superseded' }; + } + throw error; + } + const release = await session.api.getRelease(); + const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; + const assets = release + ? ( await session.api.listReleaseAssets( release.id ) ).filter( + ( asset ) => asset.name.startsWith( prefix ) + ) + : []; + const cacheRef = `refs/pull/${ session.context.pullRequestNumber }/merge`; + const caches = ( await session.api.listActionCaches( cacheRef ) ).filter( + ( cache ) => + cache.ref === cacheRef && cache.key.startsWith( CACHE_PREFIX ) + ); + const comment = await session.api.findPreviewComment( + session.context.pullRequestNumber + ); + const assetErrors = await settle( + assets.map( ( asset ) => async () => { + await session.authorize( 'closed' ); + await session.api.deleteReleaseAsset( asset.id ); + } ) + ); + const cacheErrors = await settle( + caches.map( ( cache ) => async () => { + await session.authorize( 'closed' ); + await session.api.deleteActionCache( cache.id ); + } ) + ); + let commentErrors = []; + if ( comment && assetErrors.length === 0 ) { + commentErrors = await settle( [ + async () => { + await session.authorize( 'closed' ); + await session.api.updateComment( + comment.id, + renderPreviewComment( { status: 'expired' } ) + ); + }, + ] ); + } + const errors = [ ...assetErrors, ...cacheErrors, ...commentErrors ]; + if ( errors.length > 0 ) { + throw new AggregateError( errors, 'Pull request cleanup failed.' ); + } + return { + status: 'expired', + deletedAssets: assets.length, + deletedCaches: caches.length, + }; +} + +export async function managePullRequest( options ) { + const session = sessionFrom( options ); + return session.context.action === 'synchronize' + ? markStale( session ) + : expire( session ); +} + +async function main() { + const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const result = await managePullRequest( { + repository: process.env.GITHUB_REPOSITORY, + stagingVariable: process.env.DOCS_PREVIEW_STAGING, + token: process.env.GITHUB_TOKEN, + event, + } ); + console.log( `Code Reference lifecycle: ${ result.status }.` ); +} + +if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { + main().catch( ( error ) => { + console.error( error ); + process.exitCode = 1; + } ); +} diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs new file mode 100644 index 0000000000000..363f1a9cf4a4a --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -0,0 +1,271 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { test } from 'node:test'; + +import { managePullRequest } from '../lifecycle.mjs'; +import { createPublishedMetadata } from '../lib/publisher.mjs'; +import { + COMMENT_MARKER, + PLAYGROUND_ORIGIN, + metadataAssetName, + releaseAssetUrl, + snapshotAssetName, +} from '../lib/publication.mjs'; + +const repository = 'WordPress/wordpress-develop'; +const sourceRepository = 'contributor/wordpress-develop'; +const currentSha = 'a'.repeat( 40 ); +const previewSha = 'c'.repeat( 40 ); +const snapshotBytes = Buffer.from( 'snapshot' ); + +function pullRequest( state = 'open', labels = [] ) { + return { + number: 123, + state, + base: { ref: 'trunk' }, + head: { + sha: currentSha, + repo: { full_name: sourceRepository }, + }, + labels, + }; +} + +function event( action, state = action === 'closed' ? 'closed' : 'open' ) { + return { action, pull_request: pullRequest( state ) }; +} + +function previewMetadata() { + const snapshotFilename = snapshotAssetName( { + pullRequestNumber: 123, + sourceSha: previewSha, + workflowRunId: 300, + workflowRunAttempt: 1, + } ); + return createPublishedMetadata( + { + schemaVersion: 1, + sourceRepository, + pullRequestNumber: 123, + sourceSha: previewSha, + workflowRunId: '300', + workflowRunAttempt: 1, + runUrl: `https://github.com/${ repository }/actions/runs/300`, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename, + snapshotBytes: snapshotBytes.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( snapshotBytes ) + .digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + generationTimestamp: '2026-08-08T12:00:00.000Z', + }, + repository, + '2026-08-08T13:00:00.000Z' + ); +} + +function releaseAsset( id, name ) { + return { + id, + name, + created_at: '2026-08-08T13:00:00.000Z', + browser_download_url: releaseAssetUrl( repository, name ), + }; +} + +class FakeApi { + constructor() { + this.currentPullRequest = pullRequest(); + this.release = { id: 9 }; + this.assets = []; + this.caches = []; + this.metadata = new Map(); + this.assetBytes = new Map(); + this.comment = { id: 20, body: `${ COMMENT_MARKER }\nReady` }; + this.deletedAssets = []; + this.deletedCaches = []; + this.commentBodies = []; + this.failedAsset = null; + this.cacheRef = null; + } + + async getPullRequest() { + return this.currentPullRequest; + } + + async getRelease() { + return this.release; + } + + async listReleaseAssets() { + return [ ...this.assets ]; + } + + async listActionCaches( ref ) { + this.cacheRef = ref; + return [ ...this.caches ]; + } + + async findPreviewComment() { + return this.comment; + } + + async updateComment( id, body ) { + assert.equal( id, this.comment.id ); + this.commentBodies.push( body ); + this.comment = { id, body }; + } + + async deleteReleaseAsset( id ) { + if ( id === this.failedAsset ) { + throw new Error( 'release deletion failed' ); + } + this.deletedAssets.push( id ); + } + + async deleteActionCache( id ) { + this.deletedCaches.push( id ); + } +} + +function installPreview( api ) { + const metadata = previewMetadata(); + const metadataName = metadataAssetName( metadata.snapshotFilename ); + api.assets.push( + releaseAsset( 1, metadata.snapshotFilename ), + releaseAsset( 2, metadataName ) + ); + api.metadata.set( metadataName, metadata ); + api.assetBytes.set( metadata.snapshotFilename, snapshotBytes ); + return metadata; +} + +function publicFetch( api ) { + return async ( url ) => { + if ( url.includes( 'wordpress-playground-cors-proxy.net' ) ) { + const name = url.split( '/' ).at( -1 ); + return { + status: 200, + headers: { + get: ( header ) => + ( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } )[ header.toLowerCase() ] || null, + }, + arrayBuffer: async () => api.assetBytes.get( name ), + }; + } + const name = url.split( '/' ).at( -1 ); + return { + status: api.metadata.has( name ) ? 200 : 404, + json: async () => api.metadata.get( name ), + }; + }; +} + +function options( api, lifecycleEvent ) { + return { + repository, + stagingVariable: '', + event: lifecycleEvent, + api, + fetchImplementation: publicFetch( api ), + warning: () => {}, + }; +} + +test( 'a later unlabeled commit marks the healthy preview stale', async () => { + const api = new FakeApi(); + installPreview( api ); + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) + ); + assert.equal( result.status, 'stale' ); + assert.match( api.comment.body, /Status:\*\* Stale/ ); + assert.match( api.comment.body, new RegExp( previewSha ) ); + assert.match( api.comment.body, new RegExp( currentSha ) ); + assert.match( api.comment.body, /add the `docs-preview` label again/i ); +} ); + +test( 'a labeled synchronize event leaves the publisher in charge', async () => { + const api = new FakeApi(); + api.currentPullRequest = pullRequest( 'open', [ + { name: 'docs-preview' }, + ] ); + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) + ); + assert.equal( result.status, 'ignored' ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 'closing a PR deletes only its preview assets and scoped docs caches', async () => { + const api = new FakeApi(); + api.currentPullRequest = pullRequest( 'closed' ); + installPreview( api ); + api.assets.push( + releaseAsset( 3, `code-reference-pr-124-${ previewSha }-300-1.zip` ), + releaseAsset( 4, 'code-reference-trunk-snapshot.zip' ) + ); + api.caches.push( + { + id: 10, + ref: 'refs/pull/123/merge', + key: `docs-preview-base-v1-${ 'd'.repeat( 64 ) }`, + }, + { + id: 11, + ref: 'refs/pull/123/merge', + key: 'unrelated-cache', + }, + { + id: 12, + ref: 'refs/heads/trunk', + key: `docs-preview-base-v1-${ 'e'.repeat( 64 ) }`, + } + ); + const result = await managePullRequest( options( api, event( 'closed' ) ) ); + assert.equal( result.status, 'expired' ); + assert.deepEqual( api.deletedAssets, [ 1, 2 ] ); + assert.deepEqual( api.deletedCaches, [ 10 ] ); + assert.equal( api.cacheRef, 'refs/pull/123/merge' ); + assert.match( api.comment.body, /Status:\*\* Expired/ ); +} ); + +test( 'asset cleanup failure preserves a comment that still links live assets', async () => { + const api = new FakeApi(); + api.currentPullRequest = pullRequest( 'closed' ); + installPreview( api ); + api.failedAsset = 1; + api.caches.push( { + id: 10, + ref: 'refs/pull/123/merge', + key: `docs-preview-base-v1-${ 'd'.repeat( 64 ) }`, + } ); + await assert.rejects( + managePullRequest( options( api, event( 'closed' ) ) ), + /Pull request cleanup failed/ + ); + assert.deepEqual( api.deletedAssets, [ 2 ] ); + assert.deepEqual( api.deletedCaches, [ 10 ] ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 'a reopened PR supersedes close cleanup before any deletion', async () => { + const api = new FakeApi(); + installPreview( api ); + const result = await managePullRequest( options( api, event( 'closed' ) ) ); + assert.equal( result.status, 'superseded' ); + assert.deepEqual( api.deletedAssets, [] ); + assert.deepEqual( api.deletedCaches, [] ); +} ); From 785e45cc06cb85f00a3c37fcba25cc2c9de84009 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 13:59:27 +0400 Subject: [PATCH 20/59] Build/Test Tools: Activate Code Reference PR lifecycle Fork pull requests need trusted stale and cleanup mutations without ever running their code. Use default-branch lifecycle code, separate stale permissions from destructive cleanup, and cancel obsolete events per pull request. --- .../docs-playground-preview-lifecycle.yml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 .github/workflows/docs-playground-preview-lifecycle.yml diff --git a/.github/workflows/docs-playground-preview-lifecycle.yml b/.github/workflows/docs-playground-preview-lifecycle.yml new file mode 100644 index 0000000000000..09a2834fde15e --- /dev/null +++ b/.github/workflows/docs-playground-preview-lifecycle.yml @@ -0,0 +1,79 @@ +name: Code Reference Playground Preview Lifecycle + +on: # zizmor: ignore[dangerous-triggers] Both jobs check out and run only trusted default-branch code. + pull_request_target: + branches: + - trunk + types: + - synchronize + - closed + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: {} + +jobs: + stale: + name: Mark Code Reference preview stale + if: >- + github.event.action == 'synchronize' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 10 + permissions: + contents: read + issues: write + pull-requests: read + steps: + - name: Check out trusted default-branch lifecycle code + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Mark the published preview stale + env: + DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} + GITHUB_TOKEN: ${{ github.token }} + run: node .github/scripts/docs-playground-preview/lifecycle.mjs + + cleanup: + name: Expire Code Reference preview + if: >- + github.event.action == 'closed' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 15 + permissions: + actions: write + contents: write + issues: write + pull-requests: read + steps: + - name: Check out trusted default-branch lifecycle code + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Delete the pull request preview and caches + env: + DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} + GITHUB_TOKEN: ${{ github.token }} + run: node .github/scripts/docs-playground-preview/lifecycle.mjs From 60970c1e1f9000c25d695de9cc6ce434d9920555 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:15:36 +0400 Subject: [PATCH 21/59] Build/Test Tools: Close PR lifecycle races A missing label is not proof that an old stale run still owns the comment. Bind stale mutation to the absence of a non-skipped current-SHA build, and retain the prior attempted SHA when no healthy preview exists. Close cleanup must run after both the cache-writing build and trusted publisher. Cancel the build, queue cleanup durably behind publication, then enumerate assets and PR-scoped caches. Public proxy retries and reuse-validator deduplication remain follow-ups. Partial asset cleanup deliberately leaves the historical comment unchanged until a rerun completes deletion. --- .../docs-playground-preview/lib/github.mjs | 10 +++- .../docs-playground-preview/lib/publisher.mjs | 44 ++++++++++++++- .../docs-playground-preview/lifecycle.mjs | 54 ++++++++++++++++--- .../test/lifecycle.test.mjs | 42 ++++++++++++++- .../test/publisher.test.mjs | 14 +++++ .../docs-playground-preview-build.yml | 2 +- .../docs-playground-preview-lifecycle.yml | 27 ++++++++-- .../docs-playground-preview-publish.yml | 4 +- 8 files changed, 179 insertions(+), 18 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index 916730f808079..c9f154bdabc7f 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -111,7 +111,7 @@ export class GitHubApi { return matches[ 0 ]; } - async latestPreviewRun( run ) { + async findLatestPreviewRun( run ) { const runs = await this.pages( `/repos/${ this.repository @@ -136,6 +136,14 @@ export class GitHubApi { return current; } } + return null; + } + + async latestPreviewRun( run ) { + const latest = await this.findLatestPreviewRun( run ); + if ( latest ) { + return latest; + } throw new Error( 'No current docs preview build matches this head.' ); } diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs index 074cd99680217..ea3c4c97c6476 100644 --- a/.github/scripts/docs-playground-preview/lib/publisher.mjs +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -264,9 +264,29 @@ function previousLink( previous ) { ) }.`; } +function commentHeader( source ) { + const identity = source + ? `\n` + : ''; + return `${ COMMENT_MARKER }${ identity }\n## Code Reference documentation preview`; +} + +export function readPreviewCommentSource( body ) { + if ( typeof body !== 'string' ) { + return null; + } + const match = body.match( + // + ); + return match ? { repository: match[ 1 ], sha: match[ 2 ] } : null; +} + export function renderPreviewComment( state ) { - const header = `${ COMMENT_MARKER }\n## Code Reference documentation preview`; if ( state.status === 'ready' ) { + const header = commentHeader( { + repository: state.preview.sourceRepository, + sha: state.preview.sourceSha, + } ); return `${ header }\n\n**Status:** Ready\n\n[Open Code Reference preview](${ state.preview.publication.playgroundUrl })\n\nSource: ${ commitLink( @@ -277,6 +297,10 @@ export function renderPreviewComment( state ) { } \n[GitHub Actions run](${ state.runUrl })`; } if ( state.status === 'failed' ) { + const header = commentHeader( { + repository: state.sourceRepository, + sha: state.sourceSha, + } ); return `${ header }\n\n**Status:** Latest attempt failed\n\nThe latest attempt for ${ commitLink( state.sourceRepository, state.sourceSha @@ -285,6 +309,10 @@ export function renderPreviewComment( state ) { }).${ previousLink( state.previous ) }`; } if ( state.status === 'stale' ) { + const header = commentHeader( { + repository: state.currentRepository, + sha: state.currentSha, + } ); return `${ header }\n\n**Status:** Stale\n\nThe latest successful preview was built from ${ commitLink( state.preview.sourceRepository, state.preview.sourceSha @@ -295,7 +323,21 @@ export function renderPreviewComment( state ) { state.preview.publication.playgroundUrl })\n\nAdd the \`docs-preview\` label again to build the current commit.`; } + if ( state.status === 'stale-unavailable' ) { + const header = commentHeader( { + repository: state.currentRepository, + sha: state.currentSha, + } ); + return `${ header }\n\n**Status:** Stale\n\nThe latest preview attempt was for ${ commitLink( + state.previousRepository, + state.previousSha + ) }, but no healthy docs preview is available. The pull request is now at ${ commitLink( + state.currentRepository, + state.currentSha + ) }.\n\nAdd the \`docs-preview\` label again to build the current commit.`; + } if ( state.status === 'expired' ) { + const header = commentHeader(); return `${ header }\n\n**Status:** Expired\n\nThis pull request is closed or merged. Its Code Reference preview expired and is no longer live.`; } throw new Error( `Unknown preview comment state ${ state.status }.` ); diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index f5a5dbacd53bb..6f2c44bcf33b0 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -6,7 +6,10 @@ import { pathToFileURL } from 'node:url'; import { isDeploymentEnabled } from './lib/config.mjs'; import { GitHubApi } from './lib/github.mjs'; import { findPreviousPreview } from './lib/published.mjs'; -import { renderPreviewComment } from './lib/publisher.mjs'; +import { + readPreviewCommentSource, + renderPreviewComment, +} from './lib/publisher.mjs'; const FULL_COMMIT = /^[0-9a-f]{40}$/; const CACHE_PREFIX = 'docs-preview-base-'; @@ -50,13 +53,20 @@ function lifecycleContext( options ) { } return { action, + headBranch: pullRequest.head.ref, pullRequestNumber, sourceRepository, sourceSha: pullRequest.head.sha, }; } -function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { +function assertCurrent( + context, + pullRequest, + state, + labelMustBeAbsent, + currentBuild +) { if ( pullRequest.number !== context.pullRequestNumber || pullRequest.state !== state || @@ -67,7 +77,8 @@ function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { ( labelMustBeAbsent && pullRequest.labels?.some( ( label ) => label.name === 'docs-preview' - ) ) + ) ) || + currentBuild ) { throw new Error( 'A newer pull request state superseded this event.' ); } @@ -83,16 +94,28 @@ function sessionFrom( options ) { options.token, options.fetchImplementation ); - const authorize = async ( state, labelMustBeAbsent = false ) => { + const authorize = async ( + state, + labelMustBeAbsent = false, + buildMustBeAbsent = false + ) => { const pullRequest = await api.getPullRequest( context.pullRequestNumber ); + const currentBuild = buildMustBeAbsent + ? await api.findLatestPreviewRun( { + head_sha: context.sourceSha, + head_branch: context.headBranch, + head_repository: { full_name: context.sourceRepository }, + } ) + : null; try { return assertCurrent( context, pullRequest, state, - labelMustBeAbsent + labelMustBeAbsent, + currentBuild ); } catch ( error ) { throw new LifecycleSuperseded( error.message ); @@ -110,7 +133,7 @@ function sessionFrom( options ) { async function markStale( session ) { try { - await session.authorize( 'open', true ); + await session.authorize( 'open', true, true ); } catch ( error ) { if ( error instanceof LifecycleSuperseded ) { return { status: 'ignored' }; @@ -125,9 +148,24 @@ async function markStale( session ) { } const preview = await findPreviousPreview( session ); if ( ! preview ) { - return { status: 'unavailable' }; + const previous = readPreviewCommentSource( comment.body ); + if ( ! previous ) { + return { status: 'unavailable' }; + } + await session.authorize( 'open', true, true ); + await session.api.updateComment( + comment.id, + renderPreviewComment( { + status: 'stale-unavailable', + previousRepository: previous.repository, + previousSha: previous.sha, + currentRepository: session.context.sourceRepository, + currentSha: session.context.sourceSha, + } ) + ); + return { status: 'stale' }; } - await session.authorize( 'open', true ); + await session.authorize( 'open', true, true ); await session.api.updateComment( comment.id, renderPreviewComment( { diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index 363f1a9cf4a4a..d4e68e6c8eb4a 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -3,7 +3,10 @@ import { createHash } from 'node:crypto'; import { test } from 'node:test'; import { managePullRequest } from '../lifecycle.mjs'; -import { createPublishedMetadata } from '../lib/publisher.mjs'; +import { + createPublishedMetadata, + renderPreviewComment, +} from '../lib/publisher.mjs'; import { COMMENT_MARKER, PLAYGROUND_ORIGIN, @@ -25,6 +28,7 @@ function pullRequest( state = 'open', labels = [] ) { base: { ref: 'trunk' }, head: { sha: currentSha, + ref: 'feature', repo: { full_name: sourceRepository }, }, labels, @@ -96,12 +100,17 @@ class FakeApi { this.commentBodies = []; this.failedAsset = null; this.cacheRef = null; + this.previewBuilds = []; } async getPullRequest() { return this.currentPullRequest; } + async findLatestPreviewRun() { + return this.previewBuilds.shift() || null; + } + async getRelease() { return this.release; } @@ -209,6 +218,37 @@ test( 'a labeled synchronize event leaves the publisher in charge', async () => assert.equal( api.commentBodies.length, 0 ); } ); +test( 'a completed current-SHA build supersedes an older stale event', async () => { + const api = new FakeApi(); + installPreview( api ); + api.previewBuilds.push( null, { id: 456 } ); + await assert.rejects( + managePullRequest( options( api, event( 'synchronize' ) ) ), + /superseded/ + ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 'a stale failed attempt still tells the maintainer how to rebuild', async () => { + const api = new FakeApi(); + api.comment.body = renderPreviewComment( { + status: 'failed', + sourceRepository, + sourceSha: previewSha, + at: '2026-08-08T13:00:00.000Z', + runUrl: `https://github.com/${ repository }/actions/runs/300`, + previous: null, + } ); + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) + ); + assert.equal( result.status, 'stale' ); + assert.match( api.comment.body, /no healthy docs preview is available/ ); + assert.match( api.comment.body, new RegExp( previewSha ) ); + assert.match( api.comment.body, new RegExp( currentSha ) ); + assert.match( api.comment.body, /add the `docs-preview` label again/i ); +} ); + test( 'closing a PR deletes only its preview assets and scoped docs caches', async () => { const api = new FakeApi(); api.currentPullRequest = pullRequest( 'closed' ); diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs index 965f2ba7ef81f..36e3a6b6ee157 100644 --- a/.github/scripts/docs-playground-preview/test/publisher.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -9,6 +9,7 @@ import { assertLatestAuthorized, createPublishedMetadata, inspectHandoff, + readPreviewCommentSource, renderPreviewComment, validateCandidateFile, validatePublicationContext, @@ -256,6 +257,10 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { assert.match( ready, new RegExp( COMMENT_MARKER ) ); assert.match( ready, /Status:\*\* Ready/ ); assert.match( ready, new RegExp( sha ) ); + assert.deepEqual( readPreviewCommentSource( ready ), { + repository: preview.sourceRepository, + sha, + } ); assert.equal( ready.match( /Open Code Reference preview/g ).length, 1 ); const failed = renderPreviewComment( { @@ -279,6 +284,15 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { assert.match( stale, /add the `docs-preview` label again/i ); assert.match( stale, new RegExp( sha ) ); assert.match( stale, new RegExp( 'c'.repeat( 40 ) ) ); + const unavailable = renderPreviewComment( { + status: 'stale-unavailable', + previousRepository: preview.sourceRepository, + previousSha: sha, + currentRepository: preview.sourceRepository, + currentSha: 'c'.repeat( 40 ), + } ); + assert.match( unavailable, /no healthy docs preview is available/ ); + assert.match( unavailable, /add the `docs-preview` label again/i ); assert.match( renderPreviewComment( { status: 'expired' } ), diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml index a09a4878e7aa0..9c701b5ff40f8 100644 --- a/.github/workflows/docs-playground-preview-build.yml +++ b/.github/workflows/docs-playground-preview-build.yml @@ -8,7 +8,7 @@ on: # A newer head makes every older build obsolete for this pull request. concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + group: docs-preview-build-pr-${{ github.event.pull_request.number }} cancel-in-progress: true # Pull-request code receives no write authority or repository secrets. diff --git a/.github/workflows/docs-playground-preview-lifecycle.yml b/.github/workflows/docs-playground-preview-lifecycle.yml index 09a2834fde15e..1bb0a238319c4 100644 --- a/.github/workflows/docs-playground-preview-lifecycle.yml +++ b/.github/workflows/docs-playground-preview-lifecycle.yml @@ -8,10 +8,6 @@ on: # zizmor: ignore[dangerous-triggers] Both jobs check out and run only truste - synchronize - closed -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - permissions: {} jobs: @@ -23,7 +19,11 @@ jobs: ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) runs-on: ubuntu-24.04 timeout-minutes: 10 + concurrency: + group: docs-preview-stale-pr-${{ github.event.pull_request.number }} + cancel-in-progress: true permissions: + actions: read contents: read issues: write pull-requests: read @@ -46,14 +46,33 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: node .github/scripts/docs-playground-preview/lifecycle.mjs + quiesce-build: + name: Stop the obsolete Code Reference build + if: >- + github.event.action == 'closed' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 5 + concurrency: + group: docs-preview-build-pr-${{ github.event.pull_request.number }} + cancel-in-progress: true + steps: + - name: Wait for build cancellation + run: ':' + cleanup: name: Expire Code Reference preview + needs: quiesce-build if: >- github.event.action == 'closed' && ( github.repository == 'WordPress/wordpress-develop' || ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) runs-on: ubuntu-24.04 timeout-minutes: 15 + concurrency: + group: docs-preview-publish-${{ github.event.pull_request.head.repo.full_name }}-${{ github.event.pull_request.head.ref }} + queue: max permissions: actions: write contents: write diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index f17070aa916f2..3254bc4a736da 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -10,8 +10,8 @@ on: # zizmor: ignore[dangerous-triggers] Only default-branch code validates and # A fork head branch identifies one trunk pull request even when GitHub omits the # pull_requests array. Runs queue instead of interrupting a publication halfway. concurrency: - group: ${{ github.workflow }}-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }} - cancel-in-progress: false + group: docs-preview-publish-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }} + queue: max permissions: {} From 15f223780b852336677e4be25ce10961e2ec4ec4 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:24:25 +0400 Subject: [PATCH 22/59] Build/Test Tools: Bind stale docs comments to exact state Label absence is not ownership. Compare the exact marked comment before mutation so a newer publisher state wins. Keep the original attempted SHA across stale transitions. Enter build concurrency only from the eligible open-PR job so closed events cannot cancel cleanup. Non-blocking follow-up: the stale lifecycle job retains an unused actions: read permission. --- .../docs-playground-preview/lib/publisher.mjs | 4 +- .../docs-playground-preview/lifecycle.mjs | 49 +++++++++---------- .../test/lifecycle.test.mjs | 25 +++++++--- .../test/publisher.test.mjs | 4 ++ .../docs-playground-preview-build.yml | 10 ++-- 5 files changed, 51 insertions(+), 41 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs index ea3c4c97c6476..21a3c829aacff 100644 --- a/.github/scripts/docs-playground-preview/lib/publisher.mjs +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -325,8 +325,8 @@ export function renderPreviewComment( state ) { } if ( state.status === 'stale-unavailable' ) { const header = commentHeader( { - repository: state.currentRepository, - sha: state.currentSha, + repository: state.previousRepository, + sha: state.previousSha, } ); return `${ header }\n\n**Status:** Stale\n\nThe latest preview attempt was for ${ commitLink( state.previousRepository, diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index 6f2c44bcf33b0..ed0b2872a1576 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -53,20 +53,13 @@ function lifecycleContext( options ) { } return { action, - headBranch: pullRequest.head.ref, pullRequestNumber, sourceRepository, sourceSha: pullRequest.head.sha, }; } -function assertCurrent( - context, - pullRequest, - state, - labelMustBeAbsent, - currentBuild -) { +function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { if ( pullRequest.number !== context.pullRequestNumber || pullRequest.state !== state || @@ -77,8 +70,7 @@ function assertCurrent( ( labelMustBeAbsent && pullRequest.labels?.some( ( label ) => label.name === 'docs-preview' - ) ) || - currentBuild + ) ) ) { throw new Error( 'A newer pull request state superseded this event.' ); } @@ -94,28 +86,16 @@ function sessionFrom( options ) { options.token, options.fetchImplementation ); - const authorize = async ( - state, - labelMustBeAbsent = false, - buildMustBeAbsent = false - ) => { + const authorize = async ( state, labelMustBeAbsent = false ) => { const pullRequest = await api.getPullRequest( context.pullRequestNumber ); - const currentBuild = buildMustBeAbsent - ? await api.findLatestPreviewRun( { - head_sha: context.sourceSha, - head_branch: context.headBranch, - head_repository: { full_name: context.sourceRepository }, - } ) - : null; try { return assertCurrent( context, pullRequest, state, - labelMustBeAbsent, - currentBuild + labelMustBeAbsent ); } catch ( error ) { throw new LifecycleSuperseded( error.message ); @@ -131,9 +111,24 @@ function sessionFrom( options ) { }; } +async function authorizeStaleMutation( session, expectedComment ) { + await session.authorize( 'open', true ); + const currentComment = await session.api.findPreviewComment( + session.context.pullRequestNumber + ); + if ( + currentComment?.id !== expectedComment.id || + currentComment.body !== expectedComment.body + ) { + throw new LifecycleSuperseded( + 'A newer preview state superseded this stale event.' + ); + } +} + async function markStale( session ) { try { - await session.authorize( 'open', true, true ); + await session.authorize( 'open', true ); } catch ( error ) { if ( error instanceof LifecycleSuperseded ) { return { status: 'ignored' }; @@ -152,7 +147,7 @@ async function markStale( session ) { if ( ! previous ) { return { status: 'unavailable' }; } - await session.authorize( 'open', true, true ); + await authorizeStaleMutation( session, comment ); await session.api.updateComment( comment.id, renderPreviewComment( { @@ -165,7 +160,7 @@ async function markStale( session ) { ); return { status: 'stale' }; } - await session.authorize( 'open', true, true ); + await authorizeStaleMutation( session, comment ); await session.api.updateComment( comment.id, renderPreviewComment( { diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index d4e68e6c8eb4a..3ebe58fd79cc5 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -100,17 +100,14 @@ class FakeApi { this.commentBodies = []; this.failedAsset = null; this.cacheRef = null; - this.previewBuilds = []; + this.replacementComment = null; + this.commentReads = 0; } async getPullRequest() { return this.currentPullRequest; } - async findLatestPreviewRun() { - return this.previewBuilds.shift() || null; - } - async getRelease() { return this.release; } @@ -125,6 +122,10 @@ class FakeApi { } async findPreviewComment() { + this.commentReads++; + if ( this.commentReads > 1 && this.replacementComment ) { + return this.replacementComment; + } return this.comment; } @@ -218,10 +219,20 @@ test( 'a labeled synchronize event leaves the publisher in charge', async () => assert.equal( api.commentBodies.length, 0 ); } ); -test( 'a completed current-SHA build supersedes an older stale event', async () => { +test( 'a newer terminal comment supersedes an older stale event', async () => { const api = new FakeApi(); installPreview( api ); - api.previewBuilds.push( null, { id: 456 } ); + api.replacementComment = { + id: api.comment.id, + body: renderPreviewComment( { + status: 'failed', + sourceRepository, + sourceSha: currentSha, + at: '2026-08-09T13:00:00.000Z', + runUrl: `https://github.com/${ repository }/actions/runs/456`, + previous: previewMetadata(), + } ), + }; await assert.rejects( managePullRequest( options( api, event( 'synchronize' ) ) ), /superseded/ diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs index 36e3a6b6ee157..ba905833445e7 100644 --- a/.github/scripts/docs-playground-preview/test/publisher.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -293,6 +293,10 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { } ); assert.match( unavailable, /no healthy docs preview is available/ ); assert.match( unavailable, /add the `docs-preview` label again/i ); + assert.deepEqual( readPreviewCommentSource( unavailable ), { + repository: preview.sourceRepository, + sha, + } ); assert.match( renderPreviewComment( { status: 'expired' } ), diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml index 9c701b5ff40f8..e765c34c1d418 100644 --- a/.github/workflows/docs-playground-preview-build.yml +++ b/.github/workflows/docs-playground-preview-build.yml @@ -6,11 +6,6 @@ on: - trunk types: [ labeled, synchronize ] -# A newer head makes every older build obsolete for this pull request. -concurrency: - group: docs-preview-build-pr-${{ github.event.pull_request.number }} - cancel-in-progress: true - # Pull-request code receives no write authority or repository secrets. permissions: {} @@ -21,8 +16,13 @@ jobs: ( github.repository == 'WordPress/wordpress-develop' || ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) && github.event.pull_request.base.ref == 'trunk' && + github.event.pull_request.state == 'open' && ( ( github.event.action == 'labeled' && github.event.label.name == 'docs-preview' ) || ( github.event.action == 'synchronize' && contains( github.event.pull_request.labels.*.name, 'docs-preview' ) ) ) + # A newer eligible head makes every older build obsolete for this pull request. + concurrency: + group: docs-preview-build-pr-${{ github.event.pull_request.number }} + cancel-in-progress: true runs-on: ubuntu-24.04 timeout-minutes: 60 permissions: From 4c44ebdcca349cdda738e13649f1255fe675b4f1 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:36:12 +0400 Subject: [PATCH 23/59] Build/Test Tools: Define trunk docs publication identity The stable link needs an immutable candidate identity before it can move. Bind trunk snapshots to the exact SHA, run, attempt, runtime, and size boundary, then validate the Blueprint through the public proxy. Non-blocking follow-ups: consolidate the duplicated snapshot-size constant and document the public-Blueprint validator's boundary-4 justification. --- .../lib/publication.mjs | 41 ++- .../docs-playground-preview/lib/trunk.mjs | 299 ++++++++++++++++++ .../test/trunk.test.mjs | 271 ++++++++++++++++ 3 files changed, 595 insertions(+), 16 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/lib/trunk.mjs create mode 100644 .github/scripts/docs-playground-preview/test/trunk.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs index bc37805ff6b44..4dc02eab9e7f7 100644 --- a/.github/scripts/docs-playground-preview/lib/publication.mjs +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -4,6 +4,7 @@ export const RELEASE_TAG = 'code-reference-playground-preview'; export const COMMENT_MARKER = ''; export const PLAYGROUND_ORIGIN = 'https://playground.wordpress.net'; export const CORS_PROXY = 'https://wordpress-playground-cors-proxy.net/'; +export const SNAPSHOT_BYTES_LIMIT = 104857600; const FULL_COMMIT = /^[0-9a-f]{40}$/; const FULL_DIGEST = /^[0-9a-f]{64}$/; @@ -156,7 +157,7 @@ export async function validatePublicSnapshot( return { bytes: bytes.byteLength, sha256: digest }; } -export function validateReusableMetadata( metadata, expected ) { +export function validatePublishedSnapshotMetadata( metadata, expected ) { if ( ! metadata || typeof metadata !== 'object' || @@ -174,12 +175,9 @@ export function validateReusableMetadata( metadata, expected ) { if ( metadata.sourceRepository !== expected.sourceRepository || metadata.sourceSha !== expected.sourceSha || - metadata.pullRequestNumber !== - positiveInteger( expected.pullRequestNumber, 'pullRequestNumber' ) + metadata.pullRequestNumber !== expected.pullRequestNumber ) { - throw new Error( - 'Published metadata does not match the pull request.' - ); + throw new Error( 'Published metadata does not match its source.' ); } if ( metadata.buildStatus !== 'success' || @@ -197,16 +195,6 @@ export function validateReusableMetadata( metadata, expected ) { ) { throw new Error( 'Published snapshot identity is invalid.' ); } - const prefix = `code-reference-pr-${ metadata.pullRequestNumber }-${ metadata.sourceSha }-`; - if ( - typeof metadata.snapshotFilename !== 'string' || - ! metadata.snapshotFilename.startsWith( prefix ) || - ! /^code-reference-pr-\d+-[0-9a-f]{40}-\d+-\d+\.zip$/.test( - metadata.snapshotFilename - ) - ) { - throw new Error( 'Published snapshot filename is invalid.' ); - } if ( metadata.phpVersion !== '8.4' || metadata.resolvedWordPressBeta?.channel !== 'beta' || @@ -230,6 +218,27 @@ export function validateReusableMetadata( metadata, expected ) { return metadata; } +export function validateReusableMetadata( metadata, expected ) { + validatePublishedSnapshotMetadata( metadata, { + ...expected, + pullRequestNumber: positiveInteger( + expected.pullRequestNumber, + 'pullRequestNumber' + ), + } ); + const prefix = `code-reference-pr-${ metadata.pullRequestNumber }-${ metadata.sourceSha }-`; + if ( + typeof metadata.snapshotFilename !== 'string' || + ! metadata.snapshotFilename.startsWith( prefix ) || + ! /^code-reference-pr-\d+-[0-9a-f]{40}-\d+-\d+\.zip$/.test( + metadata.snapshotFilename + ) + ) { + throw new Error( 'Published snapshot filename is invalid.' ); + } + return metadata; +} + export function createReuseHandoff( published, identity ) { validateReusableMetadata( published, { ...identity, diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs new file mode 100644 index 0000000000000..e04c5ac0a7008 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -0,0 +1,299 @@ +import { isDeepStrictEqual } from 'node:util'; + +import { isDeploymentEnabled } from './config.mjs'; +import { + PLAYGROUND_ORIGIN, + SNAPSHOT_BYTES_LIMIT, + corsProxyUrl, + createLaunchBlueprint, + playgroundUrl, + releaseAssetUrl, + validatePublishedSnapshotMetadata, +} from './publication.mjs'; + +export const TRUNK_BUILD_WORKFLOW_NAME = + 'Code Reference Playground Preview Build'; +export const TRUNK_POINTER_ASSET = 'code-reference-trunk.json'; + +const BLUEPRINT_SCHEMA = + 'https://playground.wordpress.net/blueprint-schema.json'; +const FULL_COMMIT = /^[0-9a-f]{40}$/; +const MAXIMUM_BLUEPRINT_BYTES = 65536; + +function positiveInteger( value, label ) { + const number = Number( value ); + if ( ! Number.isSafeInteger( number ) || number < 1 ) { + throw new Error( `${ label } must be a positive integer.` ); + } + return number; +} + +function timestamp( value, label ) { + if ( + typeof value !== 'string' || + Number.isNaN( Date.parse( value ) ) || + ! value.endsWith( 'Z' ) + ) { + throw new Error( `${ label } must be a UTC timestamp.` ); + } + return value; +} + +export function trunkSnapshotAssetName( identity ) { + if ( ! FULL_COMMIT.test( identity.sourceSha || '' ) ) { + throw new Error( 'sourceSha must be a full lowercase commit hash.' ); + } + const runId = positiveInteger( identity.workflowRunId, 'workflowRunId' ); + const attempt = positiveInteger( + identity.workflowRunAttempt, + 'workflowRunAttempt' + ); + return `code-reference-trunk-${ identity.sourceSha }-${ runId }-${ attempt }.zip`; +} + +export function trunkPointerCandidateName( identity ) { + return trunkSnapshotAssetName( identity ).replace( + /^code-reference-trunk-(.+)\.zip$/, + 'code-reference-trunk-pointer-$1.json' + ); +} + +export function trunkStableBlueprintUrl( repository ) { + return releaseAssetUrl( repository, TRUNK_POINTER_ASSET ); +} + +export function trunkPlaygroundUrl( repository ) { + return `${ PLAYGROUND_ORIGIN }/?blueprint-url=${ encodeURIComponent( + corsProxyUrl( trunkStableBlueprintUrl( repository ) ) + ) }`; +} + +export function validateTrunkPublicationContext( context ) { + if ( + ! isDeploymentEnabled( context.repository, context.stagingVariable ) + ) { + throw new Error( + 'Docs preview publication is disabled in this repository.' + ); + } + const runId = positiveInteger( context.run?.id, 'Workflow run id' ); + const runAttempt = positiveInteger( + context.run?.run_attempt, + 'Workflow run attempt' + ); + if ( + runId !== positiveInteger( context.triggerRunId, 'Trigger run id' ) || + runAttempt !== + positiveInteger( context.triggerRunAttempt, 'Trigger run attempt' ) + ) { + throw new Error( + 'The triggering workflow attempt is no longer current.' + ); + } + if ( + context.run.name !== TRUNK_BUILD_WORKFLOW_NAME || + context.run.event !== 'push' || + context.run.status !== 'completed' || + context.run.head_branch !== 'trunk' + ) { + throw new Error( 'The trunk source workflow identity is invalid.' ); + } + const sourceSha = context.run.head_sha; + if ( + ! FULL_COMMIT.test( sourceSha || '' ) || + context.run.head_repository?.full_name !== context.repository + ) { + throw new Error( 'The trunk workflow source identity is invalid.' ); + } + return { + ...context, + sourceRepository: context.repository, + sourceSha, + workflowRunId: runId, + workflowRunAttempt: runAttempt, + runUrl: `https://github.com/${ context.repository }/actions/runs/${ runId }`, + }; +} + +export function assertLatestTrunkAuthorized( context ) { + const current = validateTrunkPublicationContext( context ); + if ( + context.latestRun?.id !== current.workflowRunId || + context.latestRun?.run_attempt !== current.workflowRunAttempt || + context.trunkHeadSha !== current.sourceSha + ) { + throw new Error( 'A newer trunk build superseded this attempt.' ); + } + return current; +} + +function validateCommonHandoff( metadata, context ) { + if ( + ! metadata || + typeof metadata !== 'object' || + Array.isArray( metadata ) + ) { + throw new Error( 'Handoff metadata must be an object.' ); + } + if ( + metadata.schemaVersion !== 1 || + metadata.sourceRepository !== context.sourceRepository || + metadata.pullRequestNumber !== null || + metadata.sourceSha !== context.sourceSha || + String( metadata.workflowRunId ) !== String( context.workflowRunId ) || + metadata.workflowRunAttempt !== context.workflowRunAttempt || + metadata.runUrl !== context.runUrl + ) { + throw new Error( 'Handoff metadata does not match the trunk run.' ); + } + timestamp( metadata.generationTimestamp, 'Generation timestamp' ); +} + +export function inspectTrunkHandoff( metadata, rawContext ) { + const context = validateTrunkPublicationContext( rawContext ); + validateCommonHandoff( metadata, context ); + if ( metadata.buildStatus === 'failed' ) { + return { kind: 'failed', metadata, context }; + } + if ( metadata.buildStatus !== 'success' ) { + throw new Error( 'Handoff build status is invalid.' ); + } + if ( metadata.validationStatus === 'failed' ) { + return { kind: 'invalid', metadata, context }; + } + if ( metadata.validationStatus !== 'passed' ) { + throw new Error( 'Handoff validation status is invalid.' ); + } + validatePublishedSnapshotMetadata( metadata, { + sourceRepository: context.sourceRepository, + sourceSha: context.sourceSha, + pullRequestNumber: null, + maximumBytes: SNAPSHOT_BYTES_LIMIT, + } ); + if ( + metadata.handoffType !== undefined || + metadata.snapshotFilename !== trunkSnapshotAssetName( context ) + ) { + throw new Error( 'Candidate trunk snapshot filename is invalid.' ); + } + return { kind: 'candidate', metadata, context }; +} + +export function createTrunkPublishedMetadata( + metadata, + repository, + publishedAt +) { + timestamp( publishedAt, 'Publication timestamp' ); + const snapshotUrl = releaseAssetUrl( + repository, + metadata.snapshotFilename + ); + return { + ...metadata, + publication: { + publishedAt, + snapshotUrl, + snapshotProxyUrl: corsProxyUrl( snapshotUrl ), + playgroundUrl: playgroundUrl( snapshotUrl, { + blueprintSchema: BLUEPRINT_SCHEMA, + phpVersion: metadata.phpVersion, + wordpressVersion: metadata.resolvedWordPressBeta.version, + } ), + stableBlueprintUrl: trunkStableBlueprintUrl( repository ), + stablePlaygroundUrl: trunkPlaygroundUrl( repository ), + }, + }; +} + +export function validatePublishedTrunkMetadata( + metadata, + repository, + sourceSha +) { + validatePublishedSnapshotMetadata( metadata, { + sourceRepository: repository, + sourceSha, + pullRequestNumber: null, + maximumBytes: SNAPSHOT_BYTES_LIMIT, + } ); + if ( + metadata.snapshotFilename !== + trunkSnapshotAssetName( { + sourceSha, + workflowRunId: metadata.workflowRunId, + workflowRunAttempt: metadata.workflowRunAttempt, + } ) + ) { + throw new Error( 'Published trunk snapshot filename is invalid.' ); + } + const snapshotUrl = releaseAssetUrl( + repository, + metadata.snapshotFilename + ); + if ( + metadata.publication?.snapshotUrl !== snapshotUrl || + metadata.publication?.snapshotProxyUrl !== + corsProxyUrl( snapshotUrl ) || + metadata.publication?.playgroundUrl !== + playgroundUrl( snapshotUrl, { + blueprintSchema: BLUEPRINT_SCHEMA, + phpVersion: metadata.phpVersion, + wordpressVersion: metadata.resolvedWordPressBeta.version, + } ) || + metadata.publication?.stableBlueprintUrl !== + trunkStableBlueprintUrl( repository ) || + metadata.publication?.stablePlaygroundUrl !== + trunkPlaygroundUrl( repository ) + ) { + throw new Error( 'Published trunk pointer metadata is invalid.' ); + } + timestamp( metadata.publication?.publishedAt, 'Publication timestamp' ); + return metadata; +} + +export function createTrunkBlueprint( metadata ) { + const blueprint = createLaunchBlueprint( metadata.publication.snapshotUrl, { + blueprintSchema: BLUEPRINT_SCHEMA, + phpVersion: metadata.phpVersion, + wordpressVersion: metadata.resolvedWordPressBeta.version, + } ); + blueprint.meta.description = `Latest successful Core Code Reference from ${ metadata.sourceRepository }@${ metadata.sourceSha }. Generated ${ metadata.generationTimestamp }. ${ metadata.runUrl }`; + return blueprint; +} + +export async function validatePublicBlueprint( + publicUrl, + expected, + fetchImplementation = globalThis.fetch +) { + const response = await fetchImplementation( corsProxyUrl( publicUrl ), { + headers: { Origin: PLAYGROUND_ORIGIN }, + } ); + if ( response.status !== 200 ) { + throw new Error( + `Public Blueprint returned HTTP ${ response.status } through the proxy.` + ); + } + if ( response.headers.get( 'x-playground-cors-proxy' ) !== 'true' ) { + throw new Error( 'Public Blueprint did not come through the proxy.' ); + } + const allowedOrigin = response.headers.get( 'access-control-allow-origin' ); + if ( allowedOrigin !== PLAYGROUND_ORIGIN && allowedOrigin !== '*' ) { + throw new Error( 'Public Blueprint does not allow Playground.' ); + } + const bytes = Buffer.from( await response.arrayBuffer() ); + if ( bytes.byteLength < 1 || bytes.byteLength > MAXIMUM_BLUEPRINT_BYTES ) { + throw new Error( 'Public Blueprint size is outside its boundary.' ); + } + let blueprint; + try { + blueprint = JSON.parse( bytes.toString( 'utf8' ) ); + } catch { + throw new Error( 'Public Blueprint is not JSON.' ); + } + if ( ! isDeepStrictEqual( blueprint, expected ) ) { + throw new Error( 'Public Blueprint does not identify the candidate.' ); + } + return blueprint; +} diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs new file mode 100644 index 0000000000000..05c332189e3f8 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -0,0 +1,271 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { test } from 'node:test'; + +import { + PLAYGROUND_ORIGIN, + corsProxyUrl, + releaseAssetUrl, +} from '../lib/publication.mjs'; +import { + TRUNK_POINTER_ASSET, + assertLatestTrunkAuthorized, + createTrunkBlueprint, + createTrunkPublishedMetadata, + inspectTrunkHandoff, + trunkPlaygroundUrl, + trunkPointerCandidateName, + trunkSnapshotAssetName, + trunkStableBlueprintUrl, + validatePublicBlueprint, + validatePublishedTrunkMetadata, + validateTrunkPublicationContext, +} from '../lib/trunk.mjs'; + +const repository = 'WordPress/wordpress-develop'; +const sha = 'a'.repeat( 40 ); +const snapshot = Buffer.from( 'snapshot' ); + +function context( overrides = {} ) { + const run = { + id: 456, + run_attempt: 2, + name: 'Code Reference Playground Preview Build', + event: 'push', + status: 'completed', + head_branch: 'trunk', + head_sha: sha, + head_repository: { full_name: repository }, + }; + return { + repository, + stagingVariable: '', + triggerRunId: 456, + triggerRunAttempt: 2, + run, + latestRun: run, + trunkHeadSha: sha, + ...overrides, + }; +} + +function metadata( overrides = {} ) { + const identity = { + sourceSha: sha, + workflowRunId: 456, + workflowRunAttempt: 2, + }; + return { + schemaVersion: 1, + sourceRepository: repository, + pullRequestNumber: null, + sourceSha: sha, + workflowRunId: '456', + workflowRunAttempt: 2, + runUrl: `https://github.com/${ repository }/actions/runs/456`, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename: trunkSnapshotAssetName( identity ), + snapshotBytes: snapshot.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( snapshot ) + .digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + validationFailures: [], + generationTimestamp: '2026-08-09T12:34:56.000Z', + ...overrides, + }; +} + +function headers( overrides = {} ) { + const values = { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + ...overrides, + }; + return { get: ( name ) => values[ name.toLowerCase() ] || null }; +} + +test( 'trunk assets bind the exact SHA, run, and attempt', () => { + const identity = { + sourceSha: sha, + workflowRunId: 456, + workflowRunAttempt: 2, + }; + assert.equal( + trunkSnapshotAssetName( identity ), + `code-reference-trunk-${ sha }-456-2.zip` + ); + assert.equal( + trunkPointerCandidateName( identity ), + `code-reference-trunk-pointer-${ sha }-456-2.json` + ); + assert.throws( + () => trunkSnapshotAssetName( { ...identity, sourceSha: 'short' } ), + /full lowercase commit/ + ); +} ); + +test( 'the stable trunk entry point uses the fixed public Blueprint asset', () => { + const blueprintUrl = releaseAssetUrl( repository, TRUNK_POINTER_ASSET ); + assert.equal( trunkStableBlueprintUrl( repository ), blueprintUrl ); + const launch = new URL( trunkPlaygroundUrl( repository ) ); + assert.equal( launch.origin, PLAYGROUND_ORIGIN ); + assert.equal( + launch.searchParams.get( 'blueprint-url' ), + corsProxyUrl( blueprintUrl ) + ); +} ); + +test( 'trunk publication binds the exact terminal push and latest head', () => { + const checked = validateTrunkPublicationContext( context() ); + assert.equal( checked.sourceSha, sha ); + assert.equal( checked.sourceRepository, repository ); + assert.equal( checked.workflowRunAttempt, 2 ); + assert.equal( assertLatestTrunkAuthorized( context() ).workflowRunId, 456 ); + assert.throws( + () => + validateTrunkPublicationContext( + context( { repository: 'attacker/wordpress-develop' } ) + ), + /publication is disabled/ + ); + assert.throws( + () => + validateTrunkPublicationContext( { + ...context(), + run: { ...context().run, event: 'pull_request' }, + } ), + /source workflow identity/ + ); + assert.throws( + () => + assertLatestTrunkAuthorized( { + ...context(), + trunkHeadSha: 'c'.repeat( 40 ), + } ), + /superseded/ + ); +} ); + +test( 'the trunk handoff accepts only a passed exact-run candidate', () => { + assert.equal( + inspectTrunkHandoff( metadata(), context() ).kind, + 'candidate' + ); + assert.equal( + inspectTrunkHandoff( + metadata( { validationStatus: 'failed' } ), + context() + ).kind, + 'invalid' + ); + assert.equal( + inspectTrunkHandoff( + metadata( { + buildStatus: 'failed', + validationStatus: 'not-run', + } ), + context() + ).kind, + 'failed' + ); + for ( const [ name, value, error ] of [ + [ 'pullRequestNumber', 123, /trunk run/ ], + [ 'sourceSha', 'c'.repeat( 40 ), /trunk run/ ], + [ 'workflowRunAttempt', 1, /trunk run/ ], + [ 'phpVersion', '8.5', /runtime identity/ ], + [ 'dependencyManifestDigest', 'broken', /dependency identity/ ], + [ 'snapshotFilename', 'snapshot.zip', /filename/ ], + [ 'snapshotBytes', 104857601, /snapshot identity/ ], + ] ) { + assert.throws( + () => + inspectTrunkHandoff( + metadata( { [ name ]: value } ), + context() + ), + error + ); + } +} ); + +test( 'published trunk metadata produces an exact immutable Blueprint', () => { + const published = createTrunkPublishedMetadata( + metadata(), + repository, + '2026-08-09T13:00:00.000Z' + ); + assert.equal( + validatePublishedTrunkMetadata( published, repository, sha ), + published + ); + const blueprint = createTrunkBlueprint( published ); + assert.equal( blueprint.landingPage, '/reference/' ); + assert.equal( blueprint.login, false ); + assert.equal( blueprint.features.networking, false ); + assert.equal( + blueprint.steps[ 0 ].zipFile.url, + published.publication.snapshotProxyUrl + ); + assert.match( blueprint.meta.description, new RegExp( sha ) ); + assert.match( blueprint.meta.description, /actions\/runs\/456/ ); + const broken = structuredClone( published ); + broken.publication.stableBlueprintUrl = 'https://example.test/broken'; + assert.throws( + () => validatePublishedTrunkMetadata( broken, repository, sha ), + /pointer metadata/ + ); +} ); + +test( 'the public Blueprint must arrive intact through the Playground proxy', async () => { + const expected = createTrunkBlueprint( + createTrunkPublishedMetadata( + metadata(), + repository, + '2026-08-09T13:00:00.000Z' + ) + ); + const publicUrl = trunkStableBlueprintUrl( repository ); + const fetchImplementation = async ( url, options ) => { + assert.equal( url, corsProxyUrl( publicUrl ) ); + assert.equal( options.headers.Origin, PLAYGROUND_ORIGIN ); + return { + status: 200, + headers: headers(), + arrayBuffer: async () => + Buffer.from( `${ JSON.stringify( expected ) }\n` ), + }; + }; + assert.deepEqual( + await validatePublicBlueprint( + publicUrl, + expected, + fetchImplementation + ), + expected + ); + await assert.rejects( + validatePublicBlueprint( publicUrl, expected, async () => ( { + status: 200, + headers: headers(), + arrayBuffer: async () => Buffer.from( '{}' ), + } ) ), + /does not identify/ + ); + await assert.rejects( + validatePublicBlueprint( publicUrl, expected, async () => ( { + status: 200, + headers: headers( { 'x-playground-cors-proxy': 'false' } ), + arrayBuffer: async () => Buffer.from( '{}' ), + } ) ), + /did not come through/ + ); +} ); From 92db86630006e546c3038e434346d165ff9f9865 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:37:50 +0400 Subject: [PATCH 24/59] Build/Test Tools: Add trunk publication transport The publisher cannot trust its trigger once trunk moves. Read the current trunk ref and newest workflow attempt before each mutation, and use GitHub's asset rename operation for the stable pointer transaction. Non-blocking follow-up: add direct coverage for ordering two valid trunk runs. --- .../docs-playground-preview/lib/github.mjs | 38 ++++++++++++ .../test/github.test.mjs | 61 ++++++++++++++++++- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index c9f154bdabc7f..4be19f8cc74b6 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -78,6 +78,13 @@ export class GitHubApi { ); } + async getTrunkHeadSha() { + const reference = await this.request( + `/repos/${ this.repository }/git/ref/heads/trunk` + ); + return reference.object?.sha || null; + } + getPullRequest( number ) { return this.request( `/repos/${ this.repository }/pulls/${ number }` ); } @@ -147,6 +154,30 @@ export class GitHubApi { throw new Error( 'No current docs preview build matches this head.' ); } + async latestTrunkPreviewRun() { + const runs = await this.pages( + `/repos/${ + this.repository + }/actions/workflows/${ BUILD_WORKFLOW }/runs?${ query( { + event: 'push', + branch: 'trunk', + } ) }`, + 'workflow_runs' + ); + const latest = runs + .filter( + ( run ) => + run.event === 'push' && + run.head_branch === 'trunk' && + run.head_repository?.full_name === this.repository + ) + .sort( ( left, right ) => right.id - left.id )[ 0 ]; + if ( ! latest ) { + throw new Error( 'No current trunk docs preview build exists.' ); + } + return this.getRun( latest.id ); + } + async isSkippedPreviewBuild( run ) { const jobs = await this.pages( `/repos/${ this.repository }/actions/runs/${ run.id }/attempts/${ run.run_attempt }/jobs`, @@ -202,6 +233,13 @@ export class GitHubApi { ); } + updateReleaseAsset( assetId, name ) { + return this.request( + `/repos/${ this.repository }/releases/assets/${ assetId }`, + { method: 'PATCH', json: { name } } + ); + } + deleteReleaseAsset( assetId ) { return this.request( `/repos/${ this.repository }/releases/assets/${ assetId }`, diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index 21e6334c53ef7..bbdca42be9e96 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -127,6 +127,58 @@ test( 'latest run lookup binds SHA, branch, repository, and current attempt', as assert.match( calls[ 2 ], /runs\/456\/attempts\/2\/jobs/ ); } ); +test( 'trunk lookup binds the workflow, branch, repository, and current attempt', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + calls.push( url ); + if ( url.includes( '/git/ref/heads/trunk' ) ) { + return response( { object: { sha: 'a'.repeat( 40 ) } } ); + } + if ( url.includes( '/actions/workflows/' ) ) { + return response( { + workflow_runs: [ + run( { + id: 789, + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'other/wordpress-develop', + }, + } ), + run( { + id: 456, + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'WordPress/wordpress-develop', + }, + } ), + ], + } ); + } + return response( + run( { + id: 456, + run_attempt: 2, + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'WordPress/wordpress-develop', + }, + } ) + ); + } + ); + assert.equal( await api.getTrunkHeadSha(), 'a'.repeat( 40 ) ); + assert.equal( ( await api.latestTrunkPreviewRun() ).run_attempt, 2 ); + assert.match( calls[ 1 ], /event=push/ ); + assert.match( calls[ 1 ], /branch=trunk/ ); + assert.match( calls[ 2 ], /actions\/runs\/456$/ ); +} ); + test( 'skipped trigger runs neither publish nor supersede a build', async () => { const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -181,15 +233,18 @@ test( 'release operations keep immutable names and bytes', async () => { Buffer.from( 'snapshot' ), 'application/zip' ); + await api.updateReleaseAsset( 10, 'renamed.json' ); await api.deleteReleaseAsset( 10 ); await api.listActionCaches( 'refs/pull/123/merge' ); await api.deleteActionCache( 11 ); assert.equal( calls[ 0 ].options.json.tag_name, RELEASE_TAG ); assert.match( calls[ 1 ].url, /^https:\/\/uploads\.github\.com/ ); assert.equal( calls[ 1 ].options.body.toString(), 'snapshot' ); - assert.equal( calls[ 2 ].options.method, 'DELETE' ); - assert.match( calls[ 3 ].url, /ref=refs%2Fpull%2F123%2Fmerge/ ); - assert.equal( calls[ 4 ].options.method, 'DELETE' ); + assert.equal( calls[ 2 ].options.method, 'PATCH' ); + assert.deepEqual( calls[ 2 ].options.json, { name: 'renamed.json' } ); + assert.equal( calls[ 3 ].options.method, 'DELETE' ); + assert.match( calls[ 4 ].url, /ref=refs%2Fpull%2F123%2Fmerge/ ); + assert.equal( calls[ 5 ].options.method, 'DELETE' ); } ); test( 'only the marked bot comment is updated', async () => { From d67ad638655df15311a5ada9b9f9231a2901a804 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:54:30 +0400 Subject: [PATCH 25/59] Build/Test Tools: Publish trunk docs transactionally Two asset renames can strand the stable URL between names. Validate an immutable Blueprint commit publicly, move one Git ref atomically, and re-read its SHA before deleting the previous snapshot. Unknown ref state retains both asset generations. The pointer cannot outlive the snapshot it names. Non-blocking follow-ups: exercise the stable branch URL in staging and tolerate unreachable pointer commits from failed attempts. --- .../docs-playground-preview/lib/github.mjs | 54 ++- .../lib/publication.mjs | 7 +- .../docs-playground-preview/lib/trunk.mjs | 30 +- .../docs-playground-preview/publish-trunk.mjs | 337 ++++++++++++++++++ 4 files changed, 415 insertions(+), 13 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/publish-trunk.mjs diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index 4be19f8cc74b6..f4078a40fb1eb 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -233,10 +233,58 @@ export class GitHubApi { ); } - updateReleaseAsset( assetId, name ) { + getGitReference( reference ) { return this.request( - `/repos/${ this.repository }/releases/assets/${ assetId }`, - { method: 'PATCH', json: { name } } + `/repos/${ this.repository }/git/ref/${ reference }`, + { allowNotFound: true } + ); + } + + createGitBlob( content ) { + return this.request( `/repos/${ this.repository }/git/blobs`, { + method: 'POST', + json: { content, encoding: 'utf-8' }, + } ); + } + + createGitTree( path, blobSha ) { + return this.request( `/repos/${ this.repository }/git/trees`, { + method: 'POST', + json: { + tree: [ + { + path, + mode: '100644', + type: 'blob', + sha: blobSha, + }, + ], + }, + } ); + } + + createGitCommit( message, treeSha, parentSha = null ) { + return this.request( `/repos/${ this.repository }/git/commits`, { + method: 'POST', + json: { + message, + tree: treeSha, + parents: parentSha ? [ parentSha ] : [], + }, + } ); + } + + createGitReference( reference, sha ) { + return this.request( `/repos/${ this.repository }/git/refs`, { + method: 'POST', + json: { ref: `refs/${ reference }`, sha }, + } ); + } + + updateGitReference( reference, sha ) { + return this.request( + `/repos/${ this.repository }/git/refs/${ reference }`, + { method: 'PATCH', json: { sha, force: true } } ); } diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs index 4dc02eab9e7f7..24e89063c7501 100644 --- a/.github/scripts/docs-playground-preview/lib/publication.mjs +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -67,7 +67,12 @@ export function releaseAssetUrl( repository, assetName ) { export function corsProxyUrl( publicUrl ) { const parsed = new URL( publicUrl ); - if ( parsed.protocol !== 'https:' || parsed.hostname !== 'github.com' ) { + if ( + parsed.protocol !== 'https:' || + ! [ 'github.com', 'raw.githubusercontent.com' ].includes( + parsed.hostname + ) + ) { throw new Error( 'Only public GitHub asset URLs may use the proxy.' ); } return `${ CORS_PROXY }${ publicUrl }`; diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs index e04c5ac0a7008..86638cd5cc82d 100644 --- a/.github/scripts/docs-playground-preview/lib/trunk.mjs +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -14,6 +14,7 @@ import { export const TRUNK_BUILD_WORKFLOW_NAME = 'Code Reference Playground Preview Build'; export const TRUNK_POINTER_ASSET = 'code-reference-trunk.json'; +export const TRUNK_POINTER_REF = 'heads/docs-preview-code-reference'; const BLUEPRINT_SCHEMA = 'https://playground.wordpress.net/blueprint-schema.json'; @@ -51,15 +52,15 @@ export function trunkSnapshotAssetName( identity ) { return `code-reference-trunk-${ identity.sourceSha }-${ runId }-${ attempt }.zip`; } -export function trunkPointerCandidateName( identity ) { - return trunkSnapshotAssetName( identity ).replace( - /^code-reference-trunk-(.+)\.zip$/, - 'code-reference-trunk-pointer-$1.json' - ); +export function trunkStableBlueprintUrl( repository ) { + return `https://raw.githubusercontent.com/${ repository }/docs-preview-code-reference/${ TRUNK_POINTER_ASSET }`; } -export function trunkStableBlueprintUrl( repository ) { - return releaseAssetUrl( repository, TRUNK_POINTER_ASSET ); +export function trunkBlueprintCommitUrl( repository, commitSha ) { + if ( ! FULL_COMMIT.test( commitSha || '' ) ) { + throw new Error( 'commitSha must be a full lowercase commit hash.' ); + } + return `https://raw.githubusercontent.com/${ repository }/${ commitSha }/${ TRUNK_POINTER_ASSET }`; } export function trunkPlaygroundUrl( repository ) { @@ -262,9 +263,8 @@ export function createTrunkBlueprint( metadata ) { return blueprint; } -export async function validatePublicBlueprint( +export async function readPublicBlueprint( publicUrl, - expected, fetchImplementation = globalThis.fetch ) { const response = await fetchImplementation( corsProxyUrl( publicUrl ), { @@ -292,6 +292,18 @@ export async function validatePublicBlueprint( } catch { throw new Error( 'Public Blueprint is not JSON.' ); } + return blueprint; +} + +export async function validatePublicBlueprint( + publicUrl, + expected, + fetchImplementation = globalThis.fetch +) { + const blueprint = await readPublicBlueprint( + publicUrl, + fetchImplementation + ); if ( ! isDeepStrictEqual( blueprint, expected ) ) { throw new Error( 'Public Blueprint does not identify the candidate.' ); } diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs new file mode 100644 index 0000000000000..f30b737dc6c17 --- /dev/null +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -0,0 +1,337 @@ +#!/usr/bin/env node + +import { isDeepStrictEqual } from 'node:util'; +import { readFile } from 'node:fs/promises'; +import { pathToFileURL } from 'node:url'; +import path from 'node:path'; + +import { GitHubApi } from './lib/github.mjs'; +import { + metadataAssetName, + releaseAssetUrl, + validatePublicSnapshot, +} from './lib/publication.mjs'; +import { validateCandidateFile } from './lib/publisher.mjs'; +import { + TRUNK_POINTER_ASSET, + TRUNK_POINTER_REF, + assertLatestTrunkAuthorized, + createTrunkBlueprint, + createTrunkPublishedMetadata, + inspectTrunkHandoff, + trunkBlueprintCommitUrl, + validatePublicBlueprint, + validatePublishedTrunkMetadata, + validateTrunkPublicationContext, +} from './lib/trunk.mjs'; + +class SupersededTrunkRun extends Error {} + +async function readHandoff( directory ) { + return JSON.parse( + await readFile( path.join( directory, 'build.json' ), 'utf8' ) + ); +} + +async function establishSession( options ) { + const api = + options.api || + new GitHubApi( + options.repository, + options.token, + options.fetchImplementation + ); + const run = await api.getRun( options.triggerRunId ); + const base = { + repository: options.repository, + stagingVariable: options.stagingVariable, + triggerRunId: options.triggerRunId, + triggerRunAttempt: options.triggerRunAttempt, + run, + }; + const context = validateTrunkPublicationContext( base ); + return { + api, + context, + repository: options.repository, + fetchImplementation: options.fetchImplementation || globalThis.fetch, + warning: options.warning || console.warn, + now: options.now || ( () => new Date().toISOString() ), + handoffDirectory: path.resolve( options.handoffDirectory ), + authorize: async () => { + const currentRun = await api.getRun( options.triggerRunId ); + const latestRun = await api.latestTrunkPreviewRun(); + const trunkHeadSha = await api.getTrunkHeadSha(); + try { + return assertLatestTrunkAuthorized( { + ...base, + run: currentRun, + latestRun, + trunkHeadSha, + } ); + } catch ( error ) { + throw new SupersededTrunkRun( error.message ); + } + }, + }; +} + +async function ensureRelease( session ) { + let release = await session.api.getRelease(); + if ( release ) { + return release; + } + await session.authorize(); + try { + release = await session.api.createRelease(); + } catch ( error ) { + release = await session.api.getRelease(); + if ( ! release ) { + throw error; + } + } + return release; +} + +async function validatePublicMetadata( session, asset, expected ) { + const response = await session.fetchImplementation( + asset.browser_download_url + ); + if ( response.status !== 200 ) { + throw new Error( + `Public trunk metadata returned HTTP ${ response.status }.` + ); + } + const metadata = validatePublishedTrunkMetadata( + await response.json(), + session.repository, + session.context.sourceSha + ); + if ( ! isDeepStrictEqual( metadata, expected ) ) { + throw new Error( + 'Public trunk metadata does not match the candidate.' + ); + } + return metadata; +} + +async function cleanupUploaded( session, uploaded ) { + for ( const asset of uploaded ) { + try { + await session.api.deleteReleaseAsset( asset.id ); + } catch ( error ) { + session.warning( + `Cannot remove failed trunk candidate ${ asset.name }: ${ error.message }` + ); + } + } +} + +function referenceSha( reference ) { + return reference?.object?.sha || null; +} + +async function createPointerCommit( session, previousRef, blueprint ) { + const content = `${ JSON.stringify( blueprint, null, 2 ) }\n`; + await session.authorize(); + const blob = await session.api.createGitBlob( content ); + await session.authorize(); + const tree = await session.api.createGitTree( + TRUNK_POINTER_ASSET, + blob.sha + ); + await session.authorize(); + const commit = await session.api.createGitCommit( + `Code Reference preview for ${ session.context.sourceSha }`, + tree.sha, + referenceSha( previousRef ) + ); + await validatePublicBlueprint( + trunkBlueprintCommitUrl( session.repository, commit.sha ), + blueprint, + session.fetchImplementation + ); + return commit; +} + +async function resolvePointerMutation( session, previousSha, candidateSha ) { + let current; + try { + current = referenceSha( + await session.api.getGitReference( TRUNK_POINTER_REF ) + ); + } catch ( error ) { + error.pointerStateUnknown = true; + throw error; + } + if ( current === candidateSha ) { + return true; + } + if ( current === previousSha ) { + return false; + } + const error = new Error( 'The stable trunk pointer has unknown state.' ); + error.pointerStateUnknown = true; + throw error; +} + +async function moveStablePointer( session, previousRef, commit, transaction ) { + const previousSha = referenceSha( previousRef ); + let mutationError = null; + try { + await session.authorize(); + if ( previousSha ) { + await session.api.updateGitReference( + TRUNK_POINTER_REF, + commit.sha + ); + } else { + await session.api.createGitReference( + TRUNK_POINTER_REF, + commit.sha + ); + } + } catch ( error ) { + mutationError = error; + } + const moved = await resolvePointerMutation( + session, + previousSha, + commit.sha + ); + if ( ! moved ) { + throw mutationError || new Error( 'The trunk pointer did not move.' ); + } + transaction.pointerPublished = true; +} + +async function cleanupOldTrunkAssets( session, release, keepIds ) { + const assets = await session.api.listReleaseAssets( release.id ); + for ( const asset of assets ) { + if ( + asset.name.startsWith( 'code-reference-trunk-' ) && + ! keepIds.has( asset.id ) + ) { + await session.authorize(); + await session.api.deleteReleaseAsset( asset.id ); + } + } +} + +async function publishCandidate( session, metadata, uploaded, transaction ) { + const candidateFile = path.join( + session.handoffDirectory, + metadata.snapshotFilename + ); + await validateCandidateFile( metadata, candidateFile ); + const release = await ensureRelease( session ); + const previousRef = await session.api.getGitReference( TRUNK_POINTER_REF ); + + const snapshotBytes = await readFile( candidateFile ); + await session.authorize(); + const snapshotAsset = await session.api.uploadReleaseAsset( + release.id, + metadata.snapshotFilename, + snapshotBytes, + 'application/zip' + ); + uploaded.push( snapshotAsset ); + + const published = createTrunkPublishedMetadata( + metadata, + session.repository, + session.now() + ); + const metadataBytes = Buffer.from( + `${ JSON.stringify( published, null, 2 ) }\n` + ); + await session.authorize(); + const metadataAsset = await session.api.uploadReleaseAsset( + release.id, + metadataAssetName( metadata.snapshotFilename ), + metadataBytes, + 'application/json' + ); + uploaded.push( metadataAsset ); + + const blueprint = createTrunkBlueprint( published ); + await validatePublicSnapshot( + releaseAssetUrl( session.repository, snapshotAsset.name ), + { + bytes: metadata.snapshotBytes, + sha256: metadata.snapshotSha256, + maximumBytes: 104857600, + }, + session.fetchImplementation + ); + await validatePublicMetadata( session, metadataAsset, published ); + const pointerCommit = await createPointerCommit( + session, + previousRef, + blueprint + ); + await moveStablePointer( session, previousRef, pointerCommit, transaction ); + await cleanupOldTrunkAssets( + session, + release, + new Set( [ snapshotAsset.id, metadataAsset.id ] ) + ); + return { status: 'ready', published, pointerCommit: pointerCommit.sha }; +} + +export async function publishTrunk( options ) { + const session = await establishSession( options ); + const uploaded = []; + const transaction = { pointerPublished: false }; + try { + await session.authorize(); + if ( options.artifactAvailable === false ) { + throw new Error( 'The trunk publisher handoff is unavailable.' ); + } + const metadata = await readHandoff( session.handoffDirectory ); + const handoff = inspectTrunkHandoff( metadata, session.context ); + if ( handoff.kind === 'failed' ) { + throw new Error( + metadata.buildError || 'Trunk preview build failed.' + ); + } + if ( handoff.kind === 'invalid' ) { + return { status: 'invalid' }; + } + return await publishCandidate( + session, + metadata, + uploaded, + transaction + ); + } catch ( error ) { + if ( ! transaction.pointerPublished && ! error.pointerStateUnknown ) { + await cleanupUploaded( session, uploaded ); + } + if ( error instanceof SupersededTrunkRun ) { + return { status: 'superseded' }; + } + throw error; + } +} + +async function main() { + const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const result = await publishTrunk( { + repository: process.env.GITHUB_REPOSITORY, + stagingVariable: process.env.DOCS_PREVIEW_STAGING, + triggerRunId: event.workflow_run.id, + triggerRunAttempt: event.workflow_run.run_attempt, + handoffDirectory: process.argv[ 2 ] || 'handoff', + artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', + token: process.env.GITHUB_TOKEN, + } ); + console.log( `Code Reference trunk publisher: ${ result.status }.` ); +} + +if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { + main().catch( ( error ) => { + console.error( error ); + process.exitCode = 1; + } ); +} From 00c09d5fa95326bfdf5280550004ea238a296ed9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:55:18 +0400 Subject: [PATCH 26/59] Build/Test Tools: Test trunk publication recovery The pointer transaction is only useful if failures cannot erase its target. Cover public candidate rejection, atomic-ref ambiguity, unknown ref state, cleanup failure, and strict mutation ordering. Non-blocking follow-ups: assert metadata-fetch ordering and unchanged ref identity in invalid terminal cases directly. --- .../test/github.test.mjs | 55 +- .../test/publish-trunk.test.mjs | 486 ++++++++++++++++++ .../test/trunk.test.mjs | 16 +- 3 files changed, 542 insertions(+), 15 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/test/publish-trunk.test.mjs diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index bbdca42be9e96..0c445548cb38e 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -233,18 +233,61 @@ test( 'release operations keep immutable names and bytes', async () => { Buffer.from( 'snapshot' ), 'application/zip' ); - await api.updateReleaseAsset( 10, 'renamed.json' ); await api.deleteReleaseAsset( 10 ); await api.listActionCaches( 'refs/pull/123/merge' ); await api.deleteActionCache( 11 ); assert.equal( calls[ 0 ].options.json.tag_name, RELEASE_TAG ); assert.match( calls[ 1 ].url, /^https:\/\/uploads\.github\.com/ ); assert.equal( calls[ 1 ].options.body.toString(), 'snapshot' ); - assert.equal( calls[ 2 ].options.method, 'PATCH' ); - assert.deepEqual( calls[ 2 ].options.json, { name: 'renamed.json' } ); - assert.equal( calls[ 3 ].options.method, 'DELETE' ); - assert.match( calls[ 4 ].url, /ref=refs%2Fpull%2F123%2Fmerge/ ); - assert.equal( calls[ 5 ].options.method, 'DELETE' ); + assert.equal( calls[ 2 ].options.method, 'DELETE' ); + assert.match( calls[ 3 ].url, /ref=refs%2Fpull%2F123%2Fmerge/ ); + assert.equal( calls[ 4 ].options.method, 'DELETE' ); +} ); + +test( 'Git object operations create and atomically move a pointer ref', async () => { + const calls = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + calls.push( { url, options } ); + return response( { + sha: 'a'.repeat( 40 ), + object: { sha: 'b'.repeat( 40 ) }, + } ); + } + ); + await api.getGitReference( 'heads/docs-preview-code-reference' ); + await api.createGitBlob( '{"blueprint":true}\n' ); + await api.createGitTree( 'code-reference-trunk.json', 'a'.repeat( 40 ) ); + await api.createGitCommit( + 'Update Code Reference preview', + 'b'.repeat( 40 ), + 'c'.repeat( 40 ) + ); + await api.createGitReference( + 'heads/docs-preview-code-reference', + 'd'.repeat( 40 ) + ); + await api.updateGitReference( + 'heads/docs-preview-code-reference', + 'e'.repeat( 40 ) + ); + assert.match( calls[ 0 ].url, /git\/ref\/heads\/docs-preview/ ); + assert.deepEqual( calls[ 1 ].options.json, { + content: '{"blueprint":true}\n', + encoding: 'utf-8', + } ); + assert.equal( calls[ 2 ].options.json.tree[ 0 ].mode, '100644' ); + assert.deepEqual( calls[ 3 ].options.json.parents, [ 'c'.repeat( 40 ) ] ); + assert.equal( + calls[ 4 ].options.json.ref, + 'refs/heads/docs-preview-code-reference' + ); + assert.deepEqual( calls[ 5 ].options.json, { + sha: 'e'.repeat( 40 ), + force: true, + } ); } ); test( 'only the marked bot comment is updated', async () => { diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs new file mode 100644 index 0000000000000..7e873c8682efb --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -0,0 +1,486 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { mkdtemp, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { test } from 'node:test'; + +import { + PLAYGROUND_ORIGIN, + metadataAssetName, + releaseAssetUrl, +} from '../lib/publication.mjs'; +import { + TRUNK_POINTER_REF, + createTrunkBlueprint, + createTrunkPublishedMetadata, + trunkSnapshotAssetName, +} from '../lib/trunk.mjs'; +import { publishTrunk } from '../publish-trunk.mjs'; + +const repository = 'WordPress/wordpress-develop'; +const sha = 'a'.repeat( 40 ); +const snapshotBytes = Buffer.from( 'snapshot' ); + +function run( overrides = {} ) { + return { + id: 456, + run_attempt: 1, + name: 'Code Reference Playground Preview Build', + event: 'push', + status: 'completed', + head_branch: 'trunk', + head_sha: sha, + head_repository: { full_name: repository }, + ...overrides, + }; +} + +function buildMetadata( overrides = {} ) { + const sourceSha = overrides.sourceSha || sha; + const workflowRunId = overrides.workflowRunId || '456'; + const workflowRunAttempt = overrides.workflowRunAttempt || 1; + const bytes = overrides.bytes || snapshotBytes; + return { + schemaVersion: 1, + sourceRepository: repository, + pullRequestNumber: null, + sourceSha, + workflowRunId, + workflowRunAttempt, + runUrl: `https://github.com/${ repository }/actions/runs/${ workflowRunId }`, + resolvedWordPressBeta: { + channel: 'beta', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + phpVersion: '8.4', + dependencyManifestDigest: 'b'.repeat( 64 ), + snapshotFilename: trunkSnapshotAssetName( { + sourceSha, + workflowRunId, + workflowRunAttempt, + } ), + snapshotBytes: bytes.byteLength, + snapshotSha256: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), + buildStatus: 'success', + validationStatus: 'passed', + validationFailures: [], + generationTimestamp: '2026-08-09T12:34:56.000Z', + ...overrides, + }; +} + +class FakeApi { + constructor() { + this.currentRun = run(); + this.latestRun = this.currentRun; + this.trunkHeadSha = sha; + this.release = { id: 9 }; + this.assets = []; + this.assetBytes = new Map(); + this.deleted = []; + this.events = []; + this.nextId = 10; + this.deleteErrorId = null; + this.refSha = null; + this.previousRefSha = null; + this.commits = new Map(); + this.pendingBlueprint = null; + this.refReads = 0; + this.refUpdateFailure = null; + this.failRefResolution = false; + } + + async getRun() { + return this.currentRun; + } + + async latestTrunkPreviewRun() { + return this.latestRun; + } + + async getTrunkHeadSha() { + return this.trunkHeadSha; + } + + async getRelease() { + return this.release; + } + + async createRelease() { + this.release = { id: 9 }; + return this.release; + } + + async listReleaseAssets() { + return this.assets.map( ( asset ) => ( { ...asset } ) ); + } + + async uploadReleaseAsset( releaseId, name, bytes, contentType ) { + assert.equal( releaseId, 9 ); + const asset = { + id: this.nextId++, + name, + content_type: contentType, + browser_download_url: releaseAssetUrl( repository, name ), + }; + this.assets.push( asset ); + this.assetBytes.set( asset.id, Buffer.from( bytes ) ); + this.events.push( `upload:${ name }` ); + return { ...asset }; + } + + async getGitReference( reference ) { + assert.equal( reference, TRUNK_POINTER_REF ); + this.refReads++; + this.events.push( `git:read-ref:${ this.refSha }` ); + if ( this.failRefResolution && this.refReads > 1 ) { + throw new Error( 'ref resolution failed' ); + } + return this.refSha ? { object: { sha: this.refSha } } : null; + } + + async createGitBlob( content ) { + this.pendingBlueprint = content; + this.events.push( 'git:blob' ); + return { sha: 'd'.repeat( 40 ) }; + } + + async createGitTree() { + this.events.push( 'git:tree' ); + return { sha: 'e'.repeat( 40 ) }; + } + + async createGitCommit() { + const sha = 'f'.repeat( 40 ); + this.commits.set( sha, Buffer.from( this.pendingBlueprint ) ); + this.events.push( 'git:commit' ); + return { sha }; + } + + async createGitReference( reference, sha ) { + assert.equal( reference, TRUNK_POINTER_REF ); + this.refSha = sha; + this.events.push( `git:create-ref:${ sha }` ); + } + + async updateGitReference( reference, sha ) { + assert.equal( reference, TRUNK_POINTER_REF ); + if ( this.refUpdateFailure === 'before' ) { + throw new Error( 'ref update failed' ); + } + this.refSha = sha; + this.events.push( `git:update-ref:${ sha }` ); + if ( this.refUpdateFailure === 'after' ) { + throw new Error( 'ref update response failed' ); + } + } + + async deleteReleaseAsset( id ) { + if ( id === this.deleteErrorId ) { + throw new Error( 'cleanup failed' ); + } + this.deleted.push( id ); + this.events.push( `delete:${ id }` ); + this.assets = this.assets.filter( ( asset ) => asset.id !== id ); + this.assetBytes.delete( id ); + } +} + +function publicFetch( api, options = {} ) { + return async ( url ) => { + const throughProxy = url.includes( + 'wordpress-playground-cors-proxy.net' + ); + const rawStart = url.indexOf( 'https://raw.githubusercontent.com/' ); + if ( rawStart !== -1 ) { + const rawUrl = new URL( url.slice( rawStart ) ); + const parts = rawUrl.pathname.split( '/' ).filter( Boolean ); + const reference = parts[ 2 ]; + const commitSha = + reference === 'docs-preview-code-reference' + ? api.refSha + : reference; + api.events.push( + `fetch:${ + reference === 'docs-preview-code-reference' + ? 'stable-pointer' + : 'candidate-pointer' + }` + ); + const bytes = api.commits.get( commitSha ); + return { + status: bytes ? 200 : 404, + headers: { + get: ( header ) => + ( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } )[ header.toLowerCase() ] || null, + }, + arrayBuffer: async () => bytes, + }; + } + const name = new URL( + throughProxy + ? url.slice( url.indexOf( 'https://github.com/' ) ) + : url + ).pathname + .split( '/' ) + .at( -1 ); + const asset = api.assets.find( + ( candidate ) => candidate.name === name + ); + api.events.push( `fetch:${ name }` ); + if ( ! asset ) { + return { status: 404, headers: { get: () => null } }; + } + let bytes = api.assetBytes.get( asset.id ); + if ( options.corruptSnapshot && asset.name.endsWith( '.zip' ) ) { + bytes = Buffer.from( 'corrupt' ); + } + return { + status: 200, + headers: { + get: ( header ) => + ( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } )[ header.toLowerCase() ] || null, + }, + arrayBuffer: async () => bytes, + json: async () => JSON.parse( bytes.toString( 'utf8' ) ), + }; + }; +} + +async function handoffDirectory( metadata, bytes = snapshotBytes ) { + const directory = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-trunk-publish-' ) + ); + await writeFile( + path.join( directory, 'build.json' ), + `${ JSON.stringify( metadata ) }\n` + ); + if ( metadata.snapshotFilename ) { + await writeFile( + path.join( directory, metadata.snapshotFilename ), + bytes + ); + } + return directory; +} + +function options( api, directory, extra = {} ) { + return { + repository, + stagingVariable: '', + triggerRunId: 456, + triggerRunAttempt: 1, + handoffDirectory: directory, + artifactAvailable: true, + api, + fetchImplementation: publicFetch( api ), + now: () => '2026-08-09T13:00:00.000Z', + warning: () => {}, + ...extra, + }; +} + +function addAsset( api, id, name, bytes ) { + api.assets.push( { + id, + name, + browser_download_url: releaseAssetUrl( repository, name ), + } ); + api.assetBytes.set( id, Buffer.from( bytes ) ); +} + +function installPrevious( api ) { + const oldSha = 'c'.repeat( 40 ); + const oldBytes = Buffer.from( 'old snapshot' ); + const build = buildMetadata( { + sourceSha: oldSha, + workflowRunId: '300', + bytes: oldBytes, + snapshotBytes: oldBytes.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( oldBytes ) + .digest( 'hex' ), + } ); + const published = createTrunkPublishedMetadata( + build, + repository, + '2026-08-08T13:00:00.000Z' + ); + addAsset( api, 1, build.snapshotFilename, oldBytes ); + addAsset( + api, + 2, + metadataAssetName( build.snapshotFilename ), + `${ JSON.stringify( published ) }\n` + ); + addAsset( api, 4, 'code-reference-pr-123-preview.zip', 'pr snapshot' ); + api.previousRefSha = '9'.repeat( 40 ); + api.refSha = api.previousRefSha; + api.commits.set( + api.refSha, + Buffer.from( + `${ JSON.stringify( createTrunkBlueprint( published ) ) }\n` + ) + ); + return { build, published }; +} + +test( 'the stable pointer moves only after every candidate is public', async () => { + const api = new FakeApi(); + installPrevious( api ); + const current = buildMetadata(); + const directory = await handoffDirectory( current ); + const result = await publishTrunk( options( api, directory ) ); + assert.equal( result.status, 'ready' ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + const blueprint = JSON.parse( + api.commits.get( api.refSha ).toString( 'utf8' ) + ); + assert.match( blueprint.meta.description, new RegExp( sha ) ); + assert.deepEqual( api.deleted.sort(), [ 1, 2 ] ); + assert.ok( api.assets.some( ( asset ) => asset.id === 4 ) ); + const candidateFetch = api.events.lastIndexOf( 'fetch:candidate-pointer' ); + const pointerMove = api.events.lastIndexOf( + `git:update-ref:${ 'f'.repeat( 40 ) }` + ); + const pointerRead = api.events.lastIndexOf( + `git:read-ref:${ 'f'.repeat( 40 ) }` + ); + const firstDelete = api.events.findIndex( ( event ) => + event.startsWith( 'delete:' ) + ); + assert.ok( + candidateFetch > -1 && + candidateFetch < pointerMove && + pointerMove < pointerRead && + pointerRead < firstDelete + ); +} ); + +test( 'public candidate failure leaves the previous pointer and snapshot intact', async () => { + const api = new FakeApi(); + installPrevious( api ); + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( + options( api, directory, { + fetchImplementation: publicFetch( api, { + corruptSnapshot: true, + } ), + } ) + ), + /Public snapshot/ + ); + assert.equal( api.refSha, api.previousRefSha ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.deepEqual( api.deleted.sort(), [ 10, 11 ] ); +} ); + +test( 'a failed ref update leaves the previous pointer intact', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.refUpdateFailure = 'before'; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( options( api, directory ) ), + /ref update failed/ + ); + assert.equal( api.refSha, api.previousRefSha ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.deepEqual( api.deleted.sort(), [ 10, 11 ] ); +} ); + +test( 'an ambiguous ref response resolves the candidate and completes', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.refUpdateFailure = 'after'; + const directory = await handoffDirectory( buildMetadata() ); + assert.equal( + ( await publishTrunk( options( api, directory ) ) ).status, + 'ready' + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.deepEqual( api.deleted.sort(), [ 1, 2 ] ); +} ); + +test( 'unresolved ref state retains both valid generations', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.refUpdateFailure = 'after'; + api.failRefResolution = true; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( options( api, directory ) ), + /ref resolution failed/ + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); + assert.deepEqual( api.deleted, [] ); +} ); + +test( 'cleanup failure keeps the new validated pointer and both snapshots', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.deleteErrorId = 1; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( options( api, directory ) ), + /cleanup failed/ + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); +} ); + +test( 'invalid, missing, and superseded handoffs never move the pointer', async () => { + const invalidApi = new FakeApi(); + installPrevious( invalidApi ); + const invalid = buildMetadata( { validationStatus: 'failed' } ); + assert.equal( + ( + await publishTrunk( + options( invalidApi, await handoffDirectory( invalid ) ) + ) + ).status, + 'invalid' + ); + assert.equal( invalidApi.assets.length, 3 ); + + const missingApi = new FakeApi(); + installPrevious( missingApi ); + await assert.rejects( + publishTrunk( + options( missingApi, await handoffDirectory( buildMetadata() ), { + artifactAvailable: false, + } ) + ), + /handoff is unavailable/ + ); + assert.equal( missingApi.assets.length, 3 ); + + const supersededApi = new FakeApi(); + installPrevious( supersededApi ); + supersededApi.latestRun = run( { id: 789 } ); + assert.equal( + ( + await publishTrunk( + options( + supersededApi, + await handoffDirectory( buildMetadata() ) + ) + ) + ).status, + 'superseded' + ); + assert.equal( supersededApi.assets.length, 3 ); +} ); diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs index 05c332189e3f8..87fa072061977 100644 --- a/.github/scripts/docs-playground-preview/test/trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -2,19 +2,16 @@ import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; import { test } from 'node:test'; -import { - PLAYGROUND_ORIGIN, - corsProxyUrl, - releaseAssetUrl, -} from '../lib/publication.mjs'; +import { PLAYGROUND_ORIGIN, corsProxyUrl } from '../lib/publication.mjs'; import { TRUNK_POINTER_ASSET, + TRUNK_POINTER_REF, assertLatestTrunkAuthorized, createTrunkBlueprint, createTrunkPublishedMetadata, inspectTrunkHandoff, trunkPlaygroundUrl, - trunkPointerCandidateName, + trunkBlueprintCommitUrl, trunkSnapshotAssetName, trunkStableBlueprintUrl, validatePublicBlueprint, @@ -104,9 +101,10 @@ test( 'trunk assets bind the exact SHA, run, and attempt', () => { `code-reference-trunk-${ sha }-456-2.zip` ); assert.equal( - trunkPointerCandidateName( identity ), - `code-reference-trunk-pointer-${ sha }-456-2.json` + trunkBlueprintCommitUrl( repository, sha ), + `https://raw.githubusercontent.com/${ repository }/${ sha }/${ TRUNK_POINTER_ASSET }` ); + assert.equal( TRUNK_POINTER_REF, 'heads/docs-preview-code-reference' ); assert.throws( () => trunkSnapshotAssetName( { ...identity, sourceSha: 'short' } ), /full lowercase commit/ @@ -114,7 +112,7 @@ test( 'trunk assets bind the exact SHA, run, and attempt', () => { } ); test( 'the stable trunk entry point uses the fixed public Blueprint asset', () => { - const blueprintUrl = releaseAssetUrl( repository, TRUNK_POINTER_ASSET ); + const blueprintUrl = `https://raw.githubusercontent.com/${ repository }/docs-preview-code-reference/${ TRUNK_POINTER_ASSET }`; assert.equal( trunkStableBlueprintUrl( repository ), blueprintUrl ); const launch = new URL( trunkPlaygroundUrl( repository ) ); assert.equal( launch.origin, PLAYGROUND_ORIGIN ); From 43f4b57ce2ae584f2c4f7b5002a57cfc7ebc7278 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 14:58:00 +0400 Subject: [PATCH 27/59] Build/Test Tools: Run docs preview on trunk pushes The shared cache and stable pointer rot if trunk does not exercise the real build. Build the exact pushed SHA with read-only authority, then hand it to queued default-branch publisher code. Non-blocking follow-ups: reduce duplicated PR/trunk orchestration and broaden the publisher concurrency comment. --- .../docs-playground-preview-build.yml | 101 ++++++++++++++++++ .../docs-playground-preview-publish.yml | 43 ++++++++ 2 files changed, 144 insertions(+) diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml index e765c34c1d418..ecb7158a4c74e 100644 --- a/.github/workflows/docs-playground-preview-build.yml +++ b/.github/workflows/docs-playground-preview-build.yml @@ -1,6 +1,9 @@ name: Code Reference Playground Preview Build on: + push: + branches: + - trunk pull_request: branches: - trunk @@ -13,6 +16,7 @@ jobs: build: name: Build Code Reference snapshot if: >- + github.event_name == 'pull_request' && ( github.repository == 'WordPress/wordpress-develop' || ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) && github.event.pull_request.base.ref == 'trunk' && @@ -135,3 +139,100 @@ jobs: path: ${{ env.HANDOFF_DIRECTORY }} if-no-files-found: error retention-days: 1 + + build-trunk: + name: Build trunk Code Reference snapshot + if: >- + github.event_name == 'push' && + github.ref == 'refs/heads/trunk' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + concurrency: + group: docs-preview-build-trunk + cancel-in-progress: true + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: read + env: + SOURCE_REPOSITORY: ${{ github.repository }} + SOURCE_SHA: ${{ github.sha }} + WORKFLOW_RUN_ID: ${{ github.run_id }} + WORKFLOW_RUN_ATTEMPT: ${{ github.run_attempt }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + HANDOFF_DIRECTORY: ${{ github.workspace }}/handoff + RESOLVED_INPUTS: ${{ runner.temp }}/docs-preview-resolved-inputs.json + CACHE_ROOT: ${{ runner.temp }}/docs-preview-cache + WORK_ROOT: ${{ runner.temp }}/docs-preview-work + SNAPSHOT_NAME: code-reference-trunk-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}.zip + steps: + - name: Check out the exact trunk commit + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Set up the pinned PHP and Composer versions + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 + with: + php-version: '8.4' + tools: composer:2.8.12 + coverage: none + + - name: Resolve the exact build and cache identity + id: resolve + run: >- + npm --prefix .github/docs-playground-preview run build -- + --resolve-only + --source "$GITHUB_WORKSPACE" + --source-repository "$SOURCE_REPOSITORY" + --source-sha "$SOURCE_SHA" + --run-id "$WORKFLOW_RUN_ID" + --run-attempt "$WORKFLOW_RUN_ATTEMPT" + --run-url "$RUN_URL" + --runner-image ubuntu-24.04 + --cache-root "$CACHE_ROOT" + --work-root "$WORK_ROOT" + --inputs-output "$RESOLVED_INPUTS" + --metadata "$HANDOFF_DIRECTORY/build.json" + + - name: Restore the exact invariant site base + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ steps.resolve.outputs.cache-directory }} + key: ${{ steps.resolve.outputs.cache-key }} + + # Administrator: enable enforcement in Settings > Secrets and variables > + # Actions > Variables by creating or updating DOCS_PREVIEW_ENFORCE to true. + - name: Build and validate the trunk Code Reference snapshot + env: + DOCS_PREVIEW_ENFORCE: ${{ vars.DOCS_PREVIEW_ENFORCE }} + run: >- + npm --prefix .github/docs-playground-preview run build -- + --source "$GITHUB_WORKSPACE" + --source-repository "$SOURCE_REPOSITORY" + --source-sha "$SOURCE_SHA" + --run-id "$WORKFLOW_RUN_ID" + --run-attempt "$WORKFLOW_RUN_ATTEMPT" + --run-url "$RUN_URL" + --runner-image ubuntu-24.04 + --cache-root "$CACHE_ROOT" + --work-root "$WORK_ROOT" + --resolved-inputs "$RESOLVED_INPUTS" + --output "$HANDOFF_DIRECTORY/$SNAPSHOT_NAME" + --metadata "$HANDOFF_DIRECTORY/build.json" + + - name: Upload the terminal trunk publisher handoff + if: ${{ always() && ! cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: docs-preview-trunk-handoff-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ env.HANDOFF_DIRECTORY }} + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index 3254bc4a736da..97e48c1c41953 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -59,3 +59,46 @@ jobs: GITHUB_TOKEN: ${{ github.token }} HANDOFF_DOWNLOAD_RESULT: ${{ steps.download.outcome }} run: node .github/scripts/docs-playground-preview/publish.mjs handoff + + publish-trunk: + name: Publish trunk Code Reference snapshot + if: >- + github.event.workflow_run.event == 'push' && + github.event.workflow_run.head_branch == 'trunk' && + ( github.repository == 'WordPress/wordpress-develop' || + ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) + runs-on: ubuntu-24.04 + timeout-minutes: 30 + permissions: + actions: read + contents: write + steps: + - name: Check out trusted default-branch publisher code + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + + - name: Set up the pinned Node version + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20.20.2' + + - name: Download the exact trunk handoff + id: download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: docs-preview-trunk-handoff-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }} + path: handoff + github-token: ${{ github.token }} + run-id: ${{ github.event.workflow_run.id }} + digest-mismatch: error + + - name: Validate and publish the trunk handoff + env: + DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} + GITHUB_TOKEN: ${{ github.token }} + HANDOFF_DOWNLOAD_RESULT: ${{ steps.download.outcome }} + run: node .github/scripts/docs-playground-preview/publish-trunk.mjs handoff From cc4e8786d51863ab14227c47292df4a1310c6379 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:05:15 +0400 Subject: [PATCH 28/59] Build/Test Tools: Document Code Reference previews The preview is useless if contributors cannot operate or recover it. Document the exact local command, pins, cache scopes, label lifecycle, publication names, rollback behavior, and justified validators. Keep the repository README on one stable Blueprint URL. Trunk publication moves the ref, not this link. --- .github/docs-playground-preview/README.md | 115 ++++++++++++++++++ .../test/trunk.test.mjs | 10 ++ README.md | 2 + 3 files changed, 127 insertions(+) create mode 100644 .github/docs-playground-preview/README.md diff --git a/.github/docs-playground-preview/README.md b/.github/docs-playground-preview/README.md new file mode 100644 index 0000000000000..87906da0c3adf --- /dev/null +++ b/.github/docs-playground-preview/README.md @@ -0,0 +1,115 @@ +# Code Reference Playground preview + +This directory pins the inputs for the WordPress Core Code Reference preview. The implementation lives in `.github/scripts/docs-playground-preview`; GitHub Actions only supplies exact source identity, caching, and publication authority. + +The preview is informational. Pull request source is parsed as data in a job with no secrets and `contents: read` at most. Build jobs use GitHub's cache service: a trusted `trunk` build can warm the shared cache, while GitHub scopes a pull-request-created entry to its pull request ref so it cannot warm or replace the default-branch cache. Only default-branch publisher and cleanup code receives repository write permissions for release assets, comments, labels, cache deletion, or the stable `trunk` pointer. + +## Local build + +Use the exact Node, npm, PHP, and Composer versions in `dependencies.json`, then run: + +```sh +npm --prefix .github/docs-playground-preview run build +``` + +The command infers the current Git repository and commit, resolves the moving Playground `beta` channel, builds or restores the invariant site base, parses eligible PHP under `src`, imports the complete Code Reference, packages the snapshot, and runs the same behavioral validation as CI. Local output and cache data are written below `.cache/docs-playground-preview`. + +CI passes explicit `--source-repository`, `--source-sha`, run identity, cache, output, and metadata paths to this same command. `--resolve-only` writes the concrete beta and exact cache identity before the cache restore step. Local and CI snapshots are equivalent when their symbol counts, representative routes, search, runtime constants, and size boundary agree; their bytes need not agree. + +Run the script tests with: + +```sh +npm test --prefix .github/docs-playground-preview +``` + +## Updating pins + +All repositories in `dependencies.json` must remain on the allowed repositories enforced by `.github/scripts/docs-playground-preview/lib/config.mjs`, and every repository revision must be a full immutable commit hash. Tool versions are exact. GitHub Actions are pinned to full commit hashes in the workflow files. + +To update a pinned repository: + +1. Change its full commit in `dependencies.json`. The dependency's own lock files come from that immutable checkout; this repository does not copy or re-verify them. +2. Run the script tests and a complete local build. +3. Exercise cold and warm builds in the staging repository. + +Keep duplicated tool identities synchronized: + +- For `@wp-playground/cli`, `yarn`, `@wordpress/scripts`, or `@wordpress/i18n`, update both `dependencies.json` and the exact dependency in `package.json`, then regenerate `package-lock.json` with the manifest's exact Node and npm versions. +- For Node, update `dependencies.json`, `.nvmrc`, `package.json`'s `engines.node`, and every `setup-node` input in the build, publish, and lifecycle workflows. Select a Node distribution containing the npm version recorded in `dependencies.json`; the build rejects a different npm version. +- For PHP, update `dependencies.json`, the fixed runtime checks in `.github/scripts/docs-playground-preview/lib/config.mjs` and `.github/scripts/docs-playground-preview/lib/publication.mjs`, and both `setup-php` inputs in the build workflow. PHP remains `8.4` unless the specification changes. +- For Composer, update `dependencies.json` and both `setup-php` Composer tool specifications in the build workflow. +- For a GitHub Action, update its full commit SHA and the adjacent release comment in every workflow use. + +After any tool change, run the script tests, regenerate the lockfile when applicable, complete a local build, and exercise cold and warm staging builds. + +A manifest or harness change automatically produces a different exact cache key. Increment `cacheSchemaVersion` when the stored base layout or meaning changes incompatibly, even if no dependency pin changed. Broad restore keys are prohibited. + +## Repository activation + +The workflows run in `WordPress/wordpress-develop`. They also run in `sirreal/wordpress-develop` only when the repository Actions variable `DOCS_PREVIEW_STAGING` is exactly `true`. They remain inert in every other fork. + +The staging repository needs a `docs-preview` label and the Actions variables used for the scenario being tested. Disable staging by deleting `DOCS_PREVIEW_STAGING` or setting it to anything other than the lowercase string `true`. + +## Validation enforcement + +Behavioral validation is advisory unless the repository Actions variable `DOCS_PREVIEW_ENFORCE` is exactly `true`. Advisory failures emit workflow warnings and terminal PR state but cannot publish or replace a snapshot. Fatal build, handoff, identity, digest, size, and publication failures always fail. + +To enable enforcement: + +1. Open repository **Settings**. +2. Open **Secrets and variables → Actions → Variables**. +3. Create or update `DOCS_PREVIEW_ENFORCE` with the value `true`. + +## Pull request lifecycle + +The label name is exactly `docs-preview`, and only pull requests targeting `trunk` are eligible. + +- Adding the label requests a complete build of the exact pull request head repository and SHA. +- A healthy public snapshot for the same SHA is reused. **Re-run all jobs** on the original build bypasses reuse. +- While the label remains, a synchronized head cancels the obsolete build and requests the newest SHA. +- The latest terminal publisher removes the label after success, validation failure, or build failure. +- A later unlabeled commit retains the latest successful link, marks it stale, and asks a maintainer to add the label again. +- Closing or merging deletes only that pull request's assets and `refs/pull//merge` docs caches, then marks the historical comment expired. + +The sticky comment is separate from the general Core Playground comment and is identified by ``. + +## Publication and cleanup + +Snapshots and metadata are assets on the `code-reference-playground-preview` prerelease. + +- Pull request snapshots use `code-reference-pr----.zip` with a same-stem JSON metadata asset. Only the latest healthy pair for an open pull request is retained. +- Trunk snapshots use `code-reference-trunk---.zip` with a same-stem JSON metadata asset. +- The stable trunk Blueprint is `code-reference-trunk.json` on the dedicated `docs-preview-code-reference` Git branch. The repository README points Playground at that stable raw URL. + +Trunk publication uploads and publicly validates the immutable snapshot and metadata, creates and publicly validates an immutable Blueprint commit, then atomically moves the dedicated branch ref and re-reads its exact SHA. Only after that identity is proven are older trunk assets deleted. A failed or ambiguous ref mutation retains every snapshot the ref could identify. + +PR cleanup matches only its exact PR prefix. Trunk cleanup matches only the trunk prefix. Neither path deletes assets owned by the other or changes another pull request. + +## Recovery + +Publication failure never requires deleting the current working asset first. + +- For a PR, fix the cause and add `docs-preview` again, or use **Re-run all jobs** on the original build for a forced same-SHA rebuild. +- For `trunk`, re-run the newest trunk build or push the next commit. The next successful publisher moves the stable ref and removes orphaned trunk assets. +- If the publisher cannot determine whether the stable ref moved, it retains both old and candidate assets. Inspect the ref and the two metadata assets before removing anything manually. +- Do not delete the `docs-preview-code-reference` branch or the snapshot it names during recovery. A successful newest trunk run repairs the pointer safely. + +## Bespoke validators + +Pinned standard tools own Git, ZIP, SQLite, JSON, PHP, and process semantics. This implementation does not inspect archive grammar, database bytes, canonical serialization, descriptors, or process trees. The retained project-specific checks are limited to boundaries or product behavior that standard tools cannot understand on their own: + +- **Dependency manifest and cache identity:** checks the repository allowlist, immutable commit shape, exact tool versions, concrete beta identity, and every base input. This protects the shared default-branch cache boundary. +- **Publisher handoff identity:** binds schema, deployment repository, event, PR when applicable, exact source SHA, run ID and attempt, runtime identity, filename, size, and digest before any publication. This protects the untrusted-to-trusted publication boundary. +- **Candidate file size and digest:** uses ordinary file stat and SHA-256 tools without opening the snapshot. This enforces the publisher identity and 100 MiB boundaries. +- **Parser product inspection:** uses the standard JSON parser, then enforces eligible Core source paths, supported hook types, nonempty records, per-type catastrophic-under-count floors, and the trusted importer root. These are required section 14 product and “parse, never execute” checks; they do not validate the parser's internal format beyond the fields the importer consumes. +- **Latest-wins authorization:** re-reads current PR or `trunk` state and the newest eligible workflow attempt immediately before publication mutations. This prevents an obsolete run from moving or deleting the live preview. +- **Public snapshot delivery:** fetches the immutable snapshot through the Playground CORS proxy and checks response status, CORS headers, byte size, and SHA-256. Publication is not complete until the public product has the validated identity. +- **Public metadata identity:** downloads the just-published JSON metadata, applies the same source/runtime/snapshot identity checks, and compares its parsed value with the candidate. This prevents a wrong public metadata asset from becoming the retained pointer identity. +- **Public Blueprint and stable ref identity:** parses the small Blueprint with the standard JSON parser, checks its semantic identity through the public proxy at an immutable commit, atomically moves the dedicated Git ref, and verifies that ref's SHA. This protects transactional availability without reimplementing Git semantics. +- **Behavioral snapshot validation:** boots the final snapshot through Playground and checks the required routes, search, provenance, and runtime policy. This is the section 14 product validator; it deliberately ignores intermediate archive and database representations. + +No archive grammar, database format, canonical byte serialization, descriptor transaction, or process-tree validator is part of this pipeline. + +## Staging evidence + +Before upstream rollout, record links to the `sirreal/wordpress-develop` workflow runs and comments that demonstrate every scenario in the specification's staging acceptance gate. Evidence may be accumulated across runs. Keep the run URLs and observed SHA, cache state, comment state, public URL, route/search results, runtime policy, failure-preservation result, cleanup result, and measured public snapshot size in the eventual pull request description. diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs index 87fa072061977..b4ca1ad9f27bb 100644 --- a/.github/scripts/docs-playground-preview/test/trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -1,5 +1,6 @@ import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; import { test } from 'node:test'; import { PLAYGROUND_ORIGIN, corsProxyUrl } from '../lib/publication.mjs'; @@ -122,6 +123,15 @@ test( 'the stable trunk entry point uses the fixed public Blueprint asset', () = ); } ); +test( 'the repository README links the stable trunk entry point', async () => { + const readme = await readFile( + new URL( '../../../../README.md', import.meta.url ), + 'utf8' + ); + assert.match( readme, /latest successful Core Code Reference preview/ ); + assert.ok( readme.includes( trunkPlaygroundUrl( repository ) ) ); +} ); + test( 'trunk publication binds the exact terminal push and latest head', () => { const checked = validateTrunkPublicationContext( context() ); assert.equal( checked.sourceSha, sha ); diff --git a/README.md b/README.md index eb88e407cb612..648b0e884d292 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Welcome to the WordPress development repository! Please check out the [contributor handbook](https://make.wordpress.org/core/handbook/) for information about how to open bug reports, contribute patches, test changes, write documentation, or get involved in any way you can. +[Open the latest successful Core Code Reference preview in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https%3A%2F%2Fwordpress-playground-cors-proxy.net%2Fhttps%3A%2F%2Fraw.githubusercontent.com%2FWordPress%2Fwordpress-develop%2Fdocs-preview-code-reference%2Fcode-reference-trunk.json). + * [Getting Started](#getting-started) * [Credentials](#credentials) From 000b7ffc79c00249a647ab957076eb2787f68d46 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:09:43 +0400 Subject: [PATCH 29/59] Build/Test Tools: Validate the stable docs pointer A validated commit is not the URL contributors open. The public proxy can still serve the old Blueprint after the ref moves; deleting that snapshot then breaks the stable link. Fetch the stable URL before cleanup. If delivery has not caught up, retain both complete generations. Non-blocking follow-up: retry transient public-pointer propagation before retaining both generations. --- .github/docs-playground-preview/README.md | 2 +- .../docs-playground-preview/publish-trunk.mjs | 6 ++++ .../test/publish-trunk.test.mjs | 28 +++++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.github/docs-playground-preview/README.md b/.github/docs-playground-preview/README.md index 87906da0c3adf..346bcf51a93c3 100644 --- a/.github/docs-playground-preview/README.md +++ b/.github/docs-playground-preview/README.md @@ -34,7 +34,7 @@ To update a pinned repository: Keep duplicated tool identities synchronized: -- For `@wp-playground/cli`, `yarn`, `@wordpress/scripts`, or `@wordpress/i18n`, update both `dependencies.json` and the exact dependency in `package.json`, then regenerate `package-lock.json` with the manifest's exact Node and npm versions. +- For `@wp-playground/cli`, `yarn`, `@wordpress/scripts`, or `@wordpress/i18n`, update both `dependencies.json` and the exact dependency in `package.json`, then regenerate `package-lock.json` with the manifest's exact Node and npm versions. A Playground CLI update also requires changing its fixed version check in `.github/scripts/docs-playground-preview/lib/config.mjs`. - For Node, update `dependencies.json`, `.nvmrc`, `package.json`'s `engines.node`, and every `setup-node` input in the build, publish, and lifecycle workflows. Select a Node distribution containing the npm version recorded in `dependencies.json`; the build rejects a different npm version. - For PHP, update `dependencies.json`, the fixed runtime checks in `.github/scripts/docs-playground-preview/lib/config.mjs` and `.github/scripts/docs-playground-preview/lib/publication.mjs`, and both `setup-php` inputs in the build workflow. PHP remains `8.4` unless the specification changes. - For Composer, update `dependencies.json` and both `setup-php` Composer tool specifications in the build workflow. diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index f30b737dc6c17..3ae8e895b2558 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -20,6 +20,7 @@ import { createTrunkPublishedMetadata, inspectTrunkHandoff, trunkBlueprintCommitUrl, + trunkStableBlueprintUrl, validatePublicBlueprint, validatePublishedTrunkMetadata, validateTrunkPublicationContext, @@ -271,6 +272,11 @@ async function publishCandidate( session, metadata, uploaded, transaction ) { blueprint ); await moveStablePointer( session, previousRef, pointerCommit, transaction ); + await validatePublicBlueprint( + trunkStableBlueprintUrl( session.repository ), + blueprint, + session.fetchImplementation + ); await cleanupOldTrunkAssets( session, release, diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index 7e873c8682efb..e65fa97d34bfd 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -201,7 +201,9 @@ function publicFetch( api, options = {} ) { const reference = parts[ 2 ]; const commitSha = reference === 'docs-preview-code-reference' - ? api.refSha + ? options.staleStablePointer + ? api.previousRefSha + : api.refSha : reference; api.events.push( `fetch:${ @@ -355,6 +357,7 @@ test( 'the stable pointer moves only after every candidate is public', async () const pointerRead = api.events.lastIndexOf( `git:read-ref:${ 'f'.repeat( 40 ) }` ); + const stableFetch = api.events.lastIndexOf( 'fetch:stable-pointer' ); const firstDelete = api.events.findIndex( ( event ) => event.startsWith( 'delete:' ) ); @@ -362,10 +365,31 @@ test( 'the stable pointer moves only after every candidate is public', async () candidateFetch > -1 && candidateFetch < pointerMove && pointerMove < pointerRead && - pointerRead < firstDelete + pointerRead < stableFetch && + stableFetch < firstDelete ); } ); +test( 'stale stable delivery retains both snapshot generations', async () => { + const api = new FakeApi(); + installPrevious( api ); + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( + options( api, directory, { + fetchImplementation: publicFetch( api, { + staleStablePointer: true, + } ), + } ) + ), + /does not identify the candidate/ + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); + assert.deepEqual( api.deleted, [] ); +} ); + test( 'public candidate failure leaves the previous pointer and snapshot intact', async () => { const api = new FakeApi(); installPrevious( api ); From 77f1aafcd67cbc017ce70f1c04a6a03f8f655244 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:17:46 +0400 Subject: [PATCH 30/59] Build/Test Tools: Fix docs workflow runner paths Job-level environment expressions cannot read the runner context. Both preview builds would fail workflow validation before the local pipeline started. Use the runner-provided temporary directory inside each shell step. Keep the required publication queue and narrowly silence the repository's older actionlint for that one current GitHub syntax key. Non-blocking follow-up: upgrade actionlint when it accepts GitHub's current concurrency queue key, then remove the narrow suppressions. --- .github/actionlint.yaml | 8 +++++ .../docs-playground-preview-build.yml | 30 ++++++++----------- 2 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 0000000000000..6c6fb7f9878d1 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,8 @@ +paths: + .github/workflows/docs-playground-preview-publish.yml: + ignore: + # actionlint 1.7.11 predates GitHub's concurrency queue property. + - 'unexpected key "queue" for "concurrency" section' + .github/workflows/docs-playground-preview-lifecycle.yml: + ignore: + - 'unexpected key "queue" for "concurrency" section' diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml index ecb7158a4c74e..5d7a9f1f2cf59 100644 --- a/.github/workflows/docs-playground-preview-build.yml +++ b/.github/workflows/docs-playground-preview-build.yml @@ -40,9 +40,6 @@ jobs: WORKFLOW_RUN_ATTEMPT: ${{ github.run_attempt }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} HANDOFF_DIRECTORY: ${{ github.workspace }}/handoff - RESOLVED_INPUTS: ${{ runner.temp }}/docs-preview-resolved-inputs.json - CACHE_ROOT: ${{ runner.temp }}/docs-preview-cache - WORK_ROOT: ${{ runner.temp }}/docs-preview-work SNAPSHOT_NAME: code-reference-pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-${{ github.run_id }}-${{ github.run_attempt }}.zip steps: - name: Check out the exact pull-request head @@ -97,9 +94,9 @@ jobs: --run-attempt "$WORKFLOW_RUN_ATTEMPT" --run-url "$RUN_URL" --runner-image ubuntu-24.04 - --cache-root "$CACHE_ROOT" - --work-root "$WORK_ROOT" - --inputs-output "$RESOLVED_INPUTS" + --cache-root "$RUNNER_TEMP/docs-preview-cache" + --work-root "$RUNNER_TEMP/docs-preview-work" + --inputs-output "$RUNNER_TEMP/docs-preview-resolved-inputs.json" --metadata "$HANDOFF_DIRECTORY/build.json" - name: Restore the exact invariant site base @@ -125,9 +122,9 @@ jobs: --run-attempt "$WORKFLOW_RUN_ATTEMPT" --run-url "$RUN_URL" --runner-image ubuntu-24.04 - --cache-root "$CACHE_ROOT" - --work-root "$WORK_ROOT" - --resolved-inputs "$RESOLVED_INPUTS" + --cache-root "$RUNNER_TEMP/docs-preview-cache" + --work-root "$RUNNER_TEMP/docs-preview-work" + --resolved-inputs "$RUNNER_TEMP/docs-preview-resolved-inputs.json" --output "$HANDOFF_DIRECTORY/$SNAPSHOT_NAME" --metadata "$HANDOFF_DIRECTORY/build.json" @@ -161,9 +158,6 @@ jobs: WORKFLOW_RUN_ATTEMPT: ${{ github.run_attempt }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} HANDOFF_DIRECTORY: ${{ github.workspace }}/handoff - RESOLVED_INPUTS: ${{ runner.temp }}/docs-preview-resolved-inputs.json - CACHE_ROOT: ${{ runner.temp }}/docs-preview-cache - WORK_ROOT: ${{ runner.temp }}/docs-preview-work SNAPSHOT_NAME: code-reference-trunk-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}.zip steps: - name: Check out the exact trunk commit @@ -197,9 +191,9 @@ jobs: --run-attempt "$WORKFLOW_RUN_ATTEMPT" --run-url "$RUN_URL" --runner-image ubuntu-24.04 - --cache-root "$CACHE_ROOT" - --work-root "$WORK_ROOT" - --inputs-output "$RESOLVED_INPUTS" + --cache-root "$RUNNER_TEMP/docs-preview-cache" + --work-root "$RUNNER_TEMP/docs-preview-work" + --inputs-output "$RUNNER_TEMP/docs-preview-resolved-inputs.json" --metadata "$HANDOFF_DIRECTORY/build.json" - name: Restore the exact invariant site base @@ -222,9 +216,9 @@ jobs: --run-attempt "$WORKFLOW_RUN_ATTEMPT" --run-url "$RUN_URL" --runner-image ubuntu-24.04 - --cache-root "$CACHE_ROOT" - --work-root "$WORK_ROOT" - --resolved-inputs "$RESOLVED_INPUTS" + --cache-root "$RUNNER_TEMP/docs-preview-cache" + --work-root "$RUNNER_TEMP/docs-preview-work" + --resolved-inputs "$RUNNER_TEMP/docs-preview-resolved-inputs.json" --output "$HANDOFF_DIRECTORY/$SNAPSHOT_NAME" --metadata "$HANDOFF_DIRECTORY/build.json" From 200908421ac4b47b13656df3f850978ac78c9528 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:22:57 +0400 Subject: [PATCH 31/59] Build/Test Tools: Apply Core style to docs harness The preview scripts passed their own tests but failed Core's JavaScript gate. Format the affected modules, write command output directly to the intended streams, and remove test-only shadowing. The transaction logic and emitted diagnostics do not change. --- .../docs-playground-preview/lib/archive.mjs | 19 +++- .../docs-playground-preview/lib/base.mjs | 105 +++++++++++++----- .../docs-playground-preview/lib/config.mjs | 28 +++-- .../docs-playground-preview/lib/files.mjs | 24 ++-- .../docs-playground-preview/lib/inputs.mjs | 5 +- .../docs-playground-preview/lib/process.mjs | 7 +- .../docs-playground-preview/lifecycle.mjs | 8 +- .../docs-playground-preview/publish-trunk.mjs | 10 +- .../docs-playground-preview/publish.mjs | 8 +- .../scripts/docs-playground-preview/reuse.mjs | 7 +- .../test/base.test.mjs | 53 ++++++--- .../test/config.test.mjs | 5 +- .../test/files.test.mjs | 56 +++++++--- .../test/publish-trunk.test.mjs | 40 +++---- 14 files changed, 255 insertions(+), 120 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/archive.mjs b/.github/scripts/docs-playground-preview/lib/archive.mjs index eba012e219dd3..d67e60cd2e25f 100644 --- a/.github/scripts/docs-playground-preview/lib/archive.mjs +++ b/.github/scripts/docs-playground-preview/lib/archive.mjs @@ -31,15 +31,22 @@ export async function zipDirectory( rootName, runImplementation = run ) { - const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-zip-' ) ); - const target = rootName === '.' ? temporary : path.join( temporary, rootName ); + const temporary = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-zip-' ) + ); + const target = + rootName === '.' ? temporary : path.join( temporary, rootName ); try { await copyDirectory( source, target, DEFAULT_EXCLUDES ); await rm( output, { force: true } ); - await runImplementation( 'zip', [ '-rq', path.resolve( output ), '.' ], { - cwd: temporary, - label: `package ${ rootName }`, - } ); + await runImplementation( + 'zip', + [ '-rq', path.resolve( output ), '.' ], + { + cwd: temporary, + label: `package ${ rootName }`, + } + ); } finally { await rm( temporary, { recursive: true, force: true } ); } diff --git a/.github/scripts/docs-playground-preview/lib/base.mjs b/.github/scripts/docs-playground-preview/lib/base.mjs index 12e776f82f0f4..88bfab55e9db6 100644 --- a/.github/scripts/docs-playground-preview/lib/base.mjs +++ b/.github/scripts/docs-playground-preview/lib/base.mjs @@ -1,11 +1,5 @@ import { fileURLToPath } from 'node:url'; -import { - cp, - mkdir, - readFile, - rm, - writeFile, -} from 'node:fs/promises'; +import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { copyDirectory, downloadFile, zipDirectory } from './archive.mjs'; @@ -14,7 +8,10 @@ import { run } from './process.mjs'; const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); const SCRIPT_ROOT = path.dirname( LIBRARY_ROOT ); -const TOOLING_ROOT = path.resolve( LIBRARY_ROOT, '../../../docs-playground-preview' ); +const TOOLING_ROOT = path.resolve( + LIBRARY_ROOT, + '../../../docs-playground-preview' +); const PHP_ROOT = path.join( SCRIPT_ROOT, 'php' ); function executable( name ) { @@ -31,7 +28,13 @@ export function dependencyBuildPlan( roots, composer ) { return [ { command: 'php', - args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + args: [ + composer, + 'install', + '--no-interaction', + '--no-dev', + '--prefer-dist', + ], cwd: roots.phpdocParser, label: 'install phpdoc-parser dependencies', }, @@ -62,7 +65,13 @@ export function dependencyBuildPlan( roots, composer ) { }, { command: 'php', - args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + args: [ + composer, + 'install', + '--no-interaction', + '--no-dev', + '--prefer-dist', + ], cwd: roots.wporgMuPlugins, label: 'install wporg-mu-plugins Composer dependencies', }, @@ -74,13 +83,24 @@ export function dependencyBuildPlan( roots, composer ) { }, { command: 'php', - args: [ composer, 'config', 'allow-plugins.composer/installers', 'true' ], + args: [ + composer, + 'config', + 'allow-plugins.composer/installers', + 'true', + ], cwd: roots.postsToPosts, label: 'configure posts-to-posts installer', }, { command: 'php', - args: [ composer, 'install', '--no-interaction', '--no-dev', '--prefer-dist' ], + args: [ + composer, + 'install', + '--no-interaction', + '--no-dev', + '--prefer-dist', + ], cwd: roots.postsToPosts, label: 'install posts-to-posts dependencies', }, @@ -104,7 +124,8 @@ export function createInvariantBaseBlueprint( inputs ) { meta: { title: 'WordPress Core Code Reference invariant base', author: 'WordPress', - description: 'Pinned DevHub dependencies with an empty reference index.', + description: + 'Pinned DevHub dependencies with an empty reference index.', }, preferredVersions: { php: inputs.dependencies.playground.phpVersion, @@ -135,15 +156,13 @@ export function createInvariantBaseBlueprint( inputs ) { themeData: bundled( 'bundles/wporg-developer-2023.zip' ), ifAlreadyInstalled: 'overwrite', }, - ...[ - 'code-syntax-block', - 'posts-to-posts', - 'phpdoc-parser', - ].map( ( plugin ) => ( { - step: 'unzip', - zipFile: bundled( `bundles/${ plugin }.zip` ), - extractToPath: '/wordpress/wp-content/plugins', - } ) ), + ...[ 'code-syntax-block', 'posts-to-posts', 'phpdoc-parser' ].map( + ( plugin ) => ( { + step: 'unzip', + zipFile: bundled( `bundles/${ plugin }.zip` ), + extractToPath: '/wordpress/wp-content/plugins', + } ) + ), { step: 'writeFile', path: '/tmp/docs-preview-configure-base.php', @@ -189,7 +208,10 @@ async function ensureComposer( inputs, tools, runImplementation ) { function repositoryRoots( upstreams, inputs ) { const root = ( name ) => path.join( upstreams, name ); const selected = ( name ) => - path.join( root( name ), inputs.dependencies.repositories[ name ].path ); + path.join( + root( name ), + inputs.dependencies.repositories[ name ].path + ); return { phpdocParser: selected( 'phpdocParser' ), wporgDeveloperTheme: selected( 'wporgDeveloper' ), @@ -223,7 +245,11 @@ async function buildInvariantBase( inputs, options ) { for ( const [ name, source, rootName ] of [ [ 'wporg-parent-2021', roots.wporgParentTheme, 'wporg-parent-2021' ], - [ 'wporg-developer-2023', roots.wporgDeveloperTheme, 'wporg-developer-2023' ], + [ + 'wporg-developer-2023', + roots.wporgDeveloperTheme, + 'wporg-developer-2023', + ], [ 'wporg-mu-plugins', roots.wporgMuPluginsFiles, '.' ], [ 'posts-to-posts', roots.postsToPosts, 'posts-to-posts' ], [ 'phpdoc-parser', roots.phpdocParser, 'phpdoc-parser' ], @@ -239,12 +265,19 @@ async function buildInvariantBase( inputs, options ) { await mkdir( path.join( work, 'php' ), { recursive: true } ); for ( const script of [ 'base-policy.php', 'configure-base.php' ] ) { - await cp( path.join( PHP_ROOT, script ), path.join( work, 'php', script ) ); + await cp( + path.join( PHP_ROOT, script ), + path.join( work, 'php', script ) + ); } const blueprint = path.join( work, 'base-blueprint.json' ); await writeFile( blueprint, - `${ JSON.stringify( createInvariantBaseBlueprint( inputs ), null, 2 ) }\n` + `${ JSON.stringify( + createInvariantBaseBlueprint( inputs ), + null, + 2 + ) }\n` ); await runImplementation( options.playgroundCli || executable( 'wp-playground-cli' ), @@ -264,7 +297,11 @@ async function buildInvariantBase( inputs, options ) { ], { label: 'build invariant Playground base' } ); - await copyDirectory( roots.phpdocParser, path.join( inputs.cacheDirectory, 'parser' ), [ '.git' ] ); + await copyDirectory( + roots.phpdocParser, + path.join( inputs.cacheDirectory, 'parser' ), + [ '.git' ] + ); await rm( work, { recursive: true, force: true } ); } @@ -274,9 +311,14 @@ export async function ensureInvariantBase( inputs, options = {} ) { const marker = JSON.parse( await readFile( markerFile, 'utf8' ) ); if ( marker.cacheKey === inputs.cacheKey && - ( await exists( path.join( inputs.cacheDirectory, 'base.zip' ) ) ) && ( await exists( - path.join( inputs.cacheDirectory, 'parser/generate-json-manually.php' ) + path.join( inputs.cacheDirectory, 'base.zip' ) + ) ) && + ( await exists( + path.join( + inputs.cacheDirectory, + 'parser/generate-json-manually.php' + ) ) ) ) { return { ...marker, cacheHit: true }; @@ -284,7 +326,10 @@ export async function ensureInvariantBase( inputs, options = {} ) { } await rm( inputs.cacheDirectory, { recursive: true, force: true } ); await mkdir( inputs.cacheDirectory, { recursive: true } ); - await ( options.buildImplementation || buildInvariantBase )( inputs, options ); + await ( options.buildImplementation || buildInvariantBase )( + inputs, + options + ); const marker = { schemaVersion: 1, cacheKey: inputs.cacheKey, diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index 9ddac2016bcbc..633ae0bf3f6fb 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -41,7 +41,9 @@ function assertDigest( value, label ) { export function validateDependencies( dependencies ) { assertObject( dependencies, 'Dependency manifest' ); if ( dependencies.schemaVersion !== 1 ) { - throw new Error( `Unsupported dependency schema ${ dependencies.schemaVersion }.` ); + throw new Error( + `Unsupported dependency schema ${ dependencies.schemaVersion }.` + ); } assertPositiveInteger( dependencies.cacheSchemaVersion, @@ -71,7 +73,9 @@ export function validateDependencies( dependencies ) { throw new Error( 'The WordPress runtime channel must be beta.' ); } if ( dependencies.playground.wordpressVersionApi !== VERSION_API ) { - throw new Error( 'The WordPress beta resolver must use the official API.' ); + throw new Error( + 'The WordPress beta resolver must use the official API.' + ); } if ( dependencies.limits?.snapshotBytes !== 104857600 ) { throw new Error( 'The snapshot limit must be exactly 100 MiB.' ); @@ -101,7 +105,9 @@ export function validateDependencies( dependencies ) { Object.keys( dependencies.repositories ).length !== Object.keys( OFFICIAL_REPOSITORIES ).length ) { - throw new Error( 'The dependency manifest contains an unknown repository.' ); + throw new Error( + 'The dependency manifest contains an unknown repository.' + ); } assertObject( dependencies.validation?.minimumSymbols, 'minimumSymbols' ); @@ -136,7 +142,9 @@ export async function resolveWordPressBeta( headers: { Accept: 'application/json' }, } ); if ( ! response.ok ) { - throw new Error( `WordPress beta API returned HTTP ${ response.status }.` ); + throw new Error( + `WordPress beta API returned HTTP ${ response.status }.` + ); } const body = await response.json(); const offer = body?.offers?.find( @@ -146,7 +154,9 @@ export async function resolveWordPressBeta( `https://downloads.wordpress.org/release/wordpress-${ candidate.version }.zip` ); if ( ! offer ) { - throw new Error( 'The WordPress beta API returned no concrete beta build.' ); + throw new Error( + 'The WordPress beta API returned no concrete beta build.' + ); } return Object.freeze( { channel: 'beta', @@ -168,7 +178,10 @@ export function makeBaseCacheKey( inputs ) { phpVersion: inputs.phpVersion, wordpressVersion: inputs.wordpressVersion, } ) ) { - if ( typeof value !== 'string' || ! /^[A-Za-z0-9_.-]+$/.test( value ) ) { + if ( + typeof value !== 'string' || + ! /^[A-Za-z0-9_.-]+$/.test( value ) + ) { throw new Error( `Cache ${ name } is invalid.` ); } } @@ -183,6 +196,7 @@ export function makeBaseCacheKey( inputs ) { export function isDeploymentEnabled( repository, stagingValue = '' ) { return ( DEPLOYMENT_REPOSITORIES.has( repository ) && - ( repository === 'WordPress/wordpress-develop' || stagingValue === 'true' ) + ( repository === 'WordPress/wordpress-develop' || + stagingValue === 'true' ) ); } diff --git a/.github/scripts/docs-playground-preview/lib/files.mjs b/.github/scripts/docs-playground-preview/lib/files.mjs index d15ee7f60788e..3028c045dd631 100644 --- a/.github/scripts/docs-playground-preview/lib/files.mjs +++ b/.github/scripts/docs-playground-preview/lib/files.mjs @@ -1,12 +1,5 @@ import { createHash } from 'node:crypto'; -import { - copyFile, - mkdir, - readdir, - readFile, - rm, - stat, -} from 'node:fs/promises'; +import { copyFile, mkdir, readdir, readFile, rm, stat } from 'node:fs/promises'; import path from 'node:path'; import { run } from './process.mjs'; @@ -31,7 +24,9 @@ export async function exists( filename ) { export async function findWordPressSourceRoot( candidate ) { const root = path.resolve( candidate ); for ( const directory of [ root, path.join( root, 'src' ) ] ) { - if ( await exists( path.join( directory, 'wp-includes/version.php' ) ) ) { + if ( + await exists( path.join( directory, 'wp-includes/version.php' ) ) + ) { return directory; } } @@ -43,7 +38,9 @@ async function listFiles( root, relative = '' ) { const entries = await readdir( path.join( root, relative ), { withFileTypes: true, } ); - for ( const entry of entries.sort( ( a, b ) => a.name.localeCompare( b.name ) ) ) { + for ( const entry of entries.sort( ( a, b ) => + a.name.localeCompare( b.name ) + ) ) { const child = relative ? `${ relative }/${ entry.name }` : entry.name; if ( entry.isDirectory() ) { files.push( ...( await listFiles( root, child ) ) ); @@ -83,7 +80,8 @@ export async function stageCorePhp( candidate, destination ) { ! relative.endsWith( '.php' ) || [ ...EXCLUDED_SOURCE_DIRECTORIES ].some( ( excluded ) => - relative === excluded || relative.startsWith( `${ excluded }/` ) + relative === excluded || + relative.startsWith( `${ excluded }/` ) ) ) { continue; @@ -94,7 +92,9 @@ export async function stageCorePhp( candidate, destination ) { count++; } if ( count === 0 ) { - throw new Error( 'The WordPress source tree contains no eligible PHP files.' ); + throw new Error( + 'The WordPress source tree contains no eligible PHP files.' + ); } return { source, destination, files: count }; } diff --git a/.github/scripts/docs-playground-preview/lib/inputs.mjs b/.github/scripts/docs-playground-preview/lib/inputs.mjs index 7247f6f442232..d7c6c7460dd62 100644 --- a/.github/scripts/docs-playground-preview/lib/inputs.mjs +++ b/.github/scripts/docs-playground-preview/lib/inputs.mjs @@ -46,7 +46,10 @@ export async function resolveBuildInputs( options ) { return { schemaVersion: 1, cacheKey, - cacheDirectory: path.join( path.resolve( options.cacheRoot ), cacheKey ), + cacheDirectory: path.join( + path.resolve( options.cacheRoot ), + cacheKey + ), cacheInputs, dependencies, wordpress, diff --git a/.github/scripts/docs-playground-preview/lib/process.mjs b/.github/scripts/docs-playground-preview/lib/process.mjs index 06cf8f6be69e1..b8c899a342052 100644 --- a/.github/scripts/docs-playground-preview/lib/process.mjs +++ b/.github/scripts/docs-playground-preview/lib/process.mjs @@ -4,7 +4,7 @@ import { writeFile } from 'node:fs/promises'; export async function run( command, args, options = {} ) { const capture = options.capture || Boolean( options.logFile ); if ( ! options.quiet ) { - console.log( `$ ${ [ command, ...args ].join( ' ' ) }` ); + process.stdout.write( `$ ${ [ command, ...args ].join( ' ' ) }\n` ); } return new Promise( ( resolve, reject ) => { @@ -25,7 +25,10 @@ export async function run( command, args, options = {} ) { child.once( 'close', ( code, signal ) => { ( async () => { if ( options.logFile ) { - await writeFile( options.logFile, `${ stdout }${ stderr }` ); + await writeFile( + options.logFile, + `${ stdout }${ stderr }` + ); } const result = { code, signal, stdout, stderr }; if ( code !== 0 && ! options.allowFailure ) { diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index ed0b2872a1576..da1a60bdce6f5 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -106,7 +106,9 @@ function sessionFrom( options ) { context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: options.warning || console.warn, + warning: + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ), authorize, }; } @@ -259,12 +261,12 @@ async function main() { token: process.env.GITHUB_TOKEN, event, } ); - console.log( `Code Reference lifecycle: ${ result.status }.` ); + process.stdout.write( `Code Reference lifecycle: ${ result.status }.\n` ); } if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { main().catch( ( error ) => { - console.error( error ); + process.stderr.write( `${ error.stack || error }\n` ); process.exitCode = 1; } ); } diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index 3ae8e895b2558..3ddd97bb134af 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -56,7 +56,9 @@ async function establishSession( options ) { context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: options.warning || console.warn, + warning: + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ), now: options.now || ( () => new Date().toISOString() ), handoffDirectory: path.resolve( options.handoffDirectory ), authorize: async () => { @@ -332,12 +334,14 @@ async function main() { artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', token: process.env.GITHUB_TOKEN, } ); - console.log( `Code Reference trunk publisher: ${ result.status }.` ); + process.stdout.write( + `Code Reference trunk publisher: ${ result.status }.\n` + ); } if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { main().catch( ( error ) => { - console.error( error ); + process.stderr.write( `${ error.stack || error }\n` ); process.exitCode = 1; } ); } diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 1f6529cd2edaa..65672e0554ba1 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -51,7 +51,9 @@ async function establishSession( options ) { context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: options.warning || console.warn, + warning: + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ), now: options.now || ( () => new Date().toISOString() ), handoffDirectory: path.resolve( options.handoffDirectory ), authorize: async () => { @@ -368,12 +370,12 @@ async function main() { artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', token: process.env.GITHUB_TOKEN, } ); - console.log( `Code Reference publisher: ${ result.status }.` ); + process.stdout.write( `Code Reference publisher: ${ result.status }.\n` ); } if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { main().catch( ( error ) => { - console.error( error ); + process.stderr.write( `${ error.stack || error }\n` ); process.exitCode = 1; } ); } diff --git a/.github/scripts/docs-playground-preview/reuse.mjs b/.github/scripts/docs-playground-preview/reuse.mjs index da58eb718a71c..05ebe2d952f7d 100644 --- a/.github/scripts/docs-playground-preview/reuse.mjs +++ b/.github/scripts/docs-playground-preview/reuse.mjs @@ -147,7 +147,8 @@ async function main() { ...options, maximumBytes: Number( options.maximumBytes ), token: process.env.GITHUB_TOKEN, - warning: ( message ) => console.warn( `::warning::${ message }` ), + warning: ( message ) => + process.stderr.write( `::warning::${ message }\n` ), } ); if ( handoff ) { await mkdir( path.dirname( options.output ), { recursive: true } ); @@ -167,8 +168,8 @@ async function main() { if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { main().catch( async ( error ) => { - console.warn( - `::warning::Same-SHA reuse check failed: ${ error.message }` + process.stderr.write( + `::warning::Same-SHA reuse check failed: ${ error.message }\n` ); if ( process.env.GITHUB_OUTPUT ) { await writeFile( process.env.GITHUB_OUTPUT, 'reused=false\n', { diff --git a/.github/scripts/docs-playground-preview/test/base.test.mjs b/.github/scripts/docs-playground-preview/test/base.test.mjs index faad291f06a81..690e3a6bbe190 100644 --- a/.github/scripts/docs-playground-preview/test/base.test.mjs +++ b/.github/scripts/docs-playground-preview/test/base.test.mjs @@ -29,7 +29,8 @@ function inputs( cacheDirectory ) { }, dependencies: { playground: { - blueprintSchema: 'https://playground.wordpress.net/blueprint-schema.json', + blueprintSchema: + 'https://playground.wordpress.net/blueprint-schema.json', phpVersion: '8.4', }, }, @@ -45,17 +46,16 @@ test( 'the invariant Blueprint installs dependencies without importing source', assert.deepEqual( blueprint.features, { networking: false } ); assert.equal( blueprint.login, false ); assert.equal( - blueprint.steps.some( ( step ) => /import|reference\.json/.test( JSON.stringify( step ) ) ), + blueprint.steps.some( ( step ) => + /import|reference\.json/.test( JSON.stringify( step ) ) + ), false ); assert.deepEqual( blueprint.steps .filter( ( step ) => step.step === 'installTheme' ) .map( ( step ) => step.themeData.path ), - [ - 'bundles/wporg-parent-2021.zip', - 'bundles/wporg-developer-2023.zip', - ] + [ 'bundles/wporg-parent-2021.zip', 'bundles/wporg-developer-2023.zip' ] ); } ); @@ -81,19 +81,30 @@ test( 'dependency build plan uses pinned harness tools and upstream locks', () = '--ignore-scripts', ] ); assert.match( plan[ 3 ].command, /node_modules\/\.bin\/wp-scripts$/ ); - assert.deepEqual( plan[ 4 ].args.slice( 0, 2 ), [ 'ci', '--ignore-scripts' ] ); + assert.deepEqual( plan[ 4 ].args.slice( 0, 2 ), [ + 'ci', + '--ignore-scripts', + ] ); } ); test( 'the invariant base marker is written last and enables exact reuse', async () => { - const cache = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-base-' ) ); + const cache = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-base-' ) + ); const resolved = inputs( path.join( cache, 'entry' ) ); let builds = 0; const buildImplementation = async ( current ) => { builds++; - await writeFile( path.join( current.cacheDirectory, 'base.zip' ), 'base' ); + await writeFile( + path.join( current.cacheDirectory, 'base.zip' ), + 'base' + ); await mkdir( path.join( current.cacheDirectory, 'parser' ) ); await writeFile( - path.join( current.cacheDirectory, 'parser/generate-json-manually.php' ), + path.join( + current.cacheDirectory, + 'parser/generate-json-manually.php' + ), ' { - const temporary = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-bundle-' ) ); + const temporary = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-bundle-' ) + ); const source = path.join( temporary, 'source' ); await mkdir( path.join( source, 'node_modules' ), { recursive: true } ); await writeFile( path.join( source, 'plugin.php' ), ' { - const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-fonts-' ) ); + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-fonts-' ) + ); const fonts = path.join( root, 'global-fonts' ); await mkdir( path.join( fonts, 'NotoSerif' ), { recursive: true } ); await writeFile( path.join( fonts, 'NotoSerif/font.woff2' ), 'large' ); @@ -144,7 +165,9 @@ test( 'unused CJK preview fonts are pruned before the size boundary', async () = '@import "./NotoSerif/NotoSerifJP/style.css";\nbody { color: black; }\n' ); await prunePreviewFonts( root ); - await assert.rejects( readFile( path.join( fonts, 'NotoSerif/font.woff2' ) ) ); + await assert.rejects( + readFile( path.join( fonts, 'NotoSerif/font.woff2' ) ) + ); assert.equal( await readFile( path.join( fonts, 'style.css' ), 'utf8' ), 'body { color: black; }\n' diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index a9d3df95822fc..adcb27fc9e85f 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -158,7 +158,10 @@ test( 'the cache key changes with every material base input', () => { dependencyDigest: 'c'.repeat( 64 ), harnessDigest: 'd'.repeat( 64 ), } ) ) { - assert.notEqual( makeBaseCacheKey( { ...inputs, [ name ]: value } ), baseline ); + assert.notEqual( + makeBaseCacheKey( { ...inputs, [ name ]: value } ), + baseline + ); } } ); diff --git a/.github/scripts/docs-playground-preview/test/files.test.mjs b/.github/scripts/docs-playground-preview/test/files.test.mjs index 8ccb1d2a85bc5..e814e9f4c0541 100644 --- a/.github/scripts/docs-playground-preview/test/files.test.mjs +++ b/.github/scripts/docs-playground-preview/test/files.test.mjs @@ -26,16 +26,22 @@ test( 'run captures output and reports ordinary child failure', async () => { ); assert.equal( result.stdout, 'ready' ); await assert.rejects( - run( process.execPath, [ '-e', 'process.stderr.write("broken");process.exit(2)' ], { - capture: true, - quiet: true, - } ), + run( + process.execPath, + [ '-e', 'process.stderr.write("broken");process.exit(2)' ], + { + capture: true, + quiet: true, + } + ), /broken/ ); } ); test( 'stageCorePhp copies only eligible Core PHP source', async () => { - const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-source-' ) ); + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-source-' ) + ); const source = path.join( root, 'src' ); for ( const relative of [ 'wp-includes/version.php', @@ -46,7 +52,10 @@ test( 'stageCorePhp copies only eligible Core PHP source', async () => { await mkdir( path.dirname( path.join( source, relative ) ), { recursive: true, } ); - await writeFile( path.join( source, relative ), ` { const result = await stageCorePhp( root, destination ); assert.equal( result.files, 2 ); assert.equal( - await readFile( path.join( destination, 'wp-admin/admin.php' ), 'utf8' ), + await readFile( + path.join( destination, 'wp-admin/admin.php' ), + 'utf8' + ), ' { } ); test( 'digestTree reflects names and contents but ignores excluded files', async () => { - const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-digest-' ) ); + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-digest-' ) + ); await writeFile( path.join( root, 'a' ), 'one' ); await writeFile( path.join( root, 'ignored' ), 'first' ); - const first = await digestTree( root, ( relative ) => relative !== 'ignored' ); + const first = await digestTree( + root, + ( relative ) => relative !== 'ignored' + ); await writeFile( path.join( root, 'ignored' ), 'second' ); assert.equal( await digestTree( root, ( relative ) => relative !== 'ignored' ), @@ -86,12 +105,16 @@ test( 'digestTree reflects names and contents but ignores excluded files', async } ); test( 'acquireRepositories uses Git with each validated full commit', async () => { - const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-repos-' ) ); + const root = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-repos-' ) + ); const calls = []; const fakeRun = async ( command, args, options ) => { calls.push( { command, args, options } ); if ( args[ 0 ] === 'clone' ) { - await mkdir( path.join( args.at( -1 ), '.git' ), { recursive: true } ); + await mkdir( path.join( args.at( -1 ), '.git' ), { + recursive: true, + } ); } }; const repositories = { @@ -127,7 +150,9 @@ test( 'acquireRepositories uses Git with each validated full commit', async () = } ); test( 'resolveBuildInputs binds the concrete beta and runner to an exact cache', async () => { - const cacheRoot = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-cache-' ) ); + const cacheRoot = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-cache-' ) + ); const fetchImplementation = async () => ( { ok: true, json: async () => ( { @@ -151,5 +176,8 @@ test( 'resolveBuildInputs binds the concrete beta and runner to an exact cache', } ); assert.equal( inputs.wordpress.version, '7.2-beta1' ); assert.match( inputs.cacheKey, /^docs-preview-base-v1-[0-9a-f]{64}$/ ); - assert.equal( inputs.cacheDirectory, path.join( cacheRoot, inputs.cacheKey ) ); + assert.equal( + inputs.cacheDirectory, + path.join( cacheRoot, inputs.cacheKey ) + ); } ); diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index e65fa97d34bfd..db1c5df673ad9 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -154,25 +154,25 @@ class FakeApi { } async createGitCommit() { - const sha = 'f'.repeat( 40 ); - this.commits.set( sha, Buffer.from( this.pendingBlueprint ) ); + const commitSha = 'f'.repeat( 40 ); + this.commits.set( commitSha, Buffer.from( this.pendingBlueprint ) ); this.events.push( 'git:commit' ); - return { sha }; + return { sha: commitSha }; } - async createGitReference( reference, sha ) { + async createGitReference( reference, candidateSha ) { assert.equal( reference, TRUNK_POINTER_REF ); - this.refSha = sha; - this.events.push( `git:create-ref:${ sha }` ); + this.refSha = candidateSha; + this.events.push( `git:create-ref:${ candidateSha }` ); } - async updateGitReference( reference, sha ) { + async updateGitReference( reference, candidateSha ) { assert.equal( reference, TRUNK_POINTER_REF ); if ( this.refUpdateFailure === 'before' ) { throw new Error( 'ref update failed' ); } - this.refSha = sha; - this.events.push( `git:update-ref:${ sha }` ); + this.refSha = candidateSha; + this.events.push( `git:update-ref:${ candidateSha }` ); if ( this.refUpdateFailure === 'after' ) { throw new Error( 'ref update response failed' ); } @@ -189,22 +189,19 @@ class FakeApi { } } -function publicFetch( api, options = {} ) { +function publicFetch( api, fetchOptions = {} ) { return async ( url ) => { - const throughProxy = url.includes( - 'wordpress-playground-cors-proxy.net' - ); const rawStart = url.indexOf( 'https://raw.githubusercontent.com/' ); if ( rawStart !== -1 ) { const rawUrl = new URL( url.slice( rawStart ) ); const parts = rawUrl.pathname.split( '/' ).filter( Boolean ); const reference = parts[ 2 ]; - const commitSha = - reference === 'docs-preview-code-reference' - ? options.staleStablePointer - ? api.previousRefSha - : api.refSha - : reference; + let commitSha = reference; + if ( reference === 'docs-preview-code-reference' ) { + commitSha = fetchOptions.staleStablePointer + ? api.previousRefSha + : api.refSha; + } api.events.push( `fetch:${ reference === 'docs-preview-code-reference' @@ -225,6 +222,9 @@ function publicFetch( api, options = {} ) { arrayBuffer: async () => bytes, }; } + const throughProxy = url.includes( + 'wordpress-playground-cors-proxy.net' + ); const name = new URL( throughProxy ? url.slice( url.indexOf( 'https://github.com/' ) ) @@ -240,7 +240,7 @@ function publicFetch( api, options = {} ) { return { status: 404, headers: { get: () => null } }; } let bytes = api.assetBytes.get( asset.id ); - if ( options.corruptSnapshot && asset.name.endsWith( '.zip' ) ) { + if ( fetchOptions.corruptSnapshot && asset.name.endsWith( '.zip' ) ) { bytes = Buffer.from( 'corrupt' ); } return { From 2b1d7cbb9a3174ad3fc62cfe3962d030cc44ad55 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:25:42 +0400 Subject: [PATCH 32/59] Build/Test Tools: Apply Core style to docs PHP The build helpers failed Core's PHP standards gate. Apply the project formatter and make the fixed five-post-type query explicit so PHPCS can verify the prepared statement without a suppression. Build and runtime behavior do not change. --- .../docs-playground-preview/php/base-policy.php | 11 +++++++---- .../docs-playground-preview/php/complete-import.php | 2 +- .../docs-playground-preview/php/configure-base.php | 13 ++++++++----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/scripts/docs-playground-preview/php/base-policy.php b/.github/scripts/docs-playground-preview/php/base-policy.php index aa8eb49b59d31..eee16d1a53607 100644 --- a/.github/scripts/docs-playground-preview/php/base-policy.php +++ b/.github/scripts/docs-playground-preview/php/base-policy.php @@ -17,16 +17,19 @@ define( 'FEATURE_2021_GLOBAL_HEADER_FOOTER', true ); } -add_filter( 'pre_option_blog_public', static function() { - return '0'; -} ); +add_filter( + 'pre_option_blog_public', + static function () { + return '0'; + } +); add_filter( 'wp_is_application_passwords_available', '__return_false' ); foreach ( array( 'update_core', 'update_plugins', 'update_themes' ) as $transient ) { add_filter( "pre_site_transient_{$transient}", - static function() { + static function () { return (object) array( 'last_checked' => time(), 'checked' => array(), diff --git a/.github/scripts/docs-playground-preview/php/complete-import.php b/.github/scripts/docs-playground-preview/php/complete-import.php index 9839af6059f13..4fab5650fbcda 100644 --- a/.github/scripts/docs-playground-preview/php/complete-import.php +++ b/.github/scripts/docs-playground-preview/php/complete-import.php @@ -32,7 +32,7 @@ $counts[ $name ] = (int) wp_count_posts( $post_type )->publish; } -$marker = array( +$marker = array( 'schemaVersion' => 1, 'stage' => 'complete-import', 'counts' => $counts, diff --git a/.github/scripts/docs-playground-preview/php/configure-base.php b/.github/scripts/docs-playground-preview/php/configure-base.php index 6b866c0b3ca72..eb8cfa0cc48c0 100644 --- a/.github/scripts/docs-playground-preview/php/configure-base.php +++ b/.github/scripts/docs-playground-preview/php/configure-base.php @@ -23,7 +23,7 @@ switch_theme( 'wporg-developer-2023' ); update_option( 'permalink_structure', '/%year%/%monthnum%/%postname%/' ); -$ensure_page = static function( $slug, $title ) { +$ensure_page = static function ( $slug, $title ) { $page = get_page_by_path( $slug, OBJECT, 'page' ); if ( $page ) { return $page->ID; @@ -75,11 +75,14 @@ 'wp-parser-method', 'wp-parser-source-file', ); -$placeholders = implode( ',', array_fill( 0, count( $reference_types ), '%s' ) ); -$count = $wpdb->get_var( +$count = $wpdb->get_var( $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type IN ({$placeholders})", - $reference_types + "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type IN ( %s, %s, %s, %s, %s )", + $reference_types[0], + $reference_types[1], + $reference_types[2], + $reference_types[3], + $reference_types[4] ) ); if ( 0 !== (int) $count ) { From 65fa1466bf2bdf0529362a60c52680cfd719340a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:28:39 +0400 Subject: [PATCH 33/59] Build/Test Tools: Preserve docs preview comment state Stale comments used the current head as their hidden source, losing the identity of the retained preview. Delayed synchronize jobs could also overwrite a terminal comment for the current head. Keep the retained preview identity and ignore only genuine terminal state for the event SHA. Otherwise the comment can claim the wrong commit or regress after publication. Non-blocking follow-ups: make terminal state machine-readable and simplify the A-to-B-to-A stale wording. --- .../docs-playground-preview/lib/publisher.mjs | 4 +- .../docs-playground-preview/lifecycle.mjs | 18 +++++++- .../test/lifecycle.test.mjs | 44 +++++++++++++++++-- .../test/publisher.test.mjs | 4 ++ 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs index 21a3c829aacff..99d7a450e4d87 100644 --- a/.github/scripts/docs-playground-preview/lib/publisher.mjs +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -310,8 +310,8 @@ export function renderPreviewComment( state ) { } if ( state.status === 'stale' ) { const header = commentHeader( { - repository: state.currentRepository, - sha: state.currentSha, + repository: state.preview.sourceRepository, + sha: state.preview.sourceSha, } ); return `${ header }\n\n**Status:** Stale\n\nThe latest successful preview was built from ${ commitLink( state.preview.sourceRepository, diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index da1a60bdce6f5..c0110077933cf 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -16,6 +16,14 @@ const CACHE_PREFIX = 'docs-preview-base-'; class LifecycleSuperseded extends Error {} +function isTerminalComment( body ) { + return ( + typeof body === 'string' && + ( body.includes( '\n\n**Status:** Ready\n\n' ) || + body.includes( '\n\n**Status:** Latest attempt failed\n\n' ) ) + ); +} + function positiveInteger( value, label ) { const number = Number( value ); if ( ! Number.isSafeInteger( number ) || number < 1 ) { @@ -143,9 +151,17 @@ async function markStale( session ) { if ( ! comment ) { return { status: 'ignored' }; } + const commentSource = readPreviewCommentSource( comment.body ); + if ( + isTerminalComment( comment.body ) && + commentSource?.repository === session.context.sourceRepository && + commentSource.sha === session.context.sourceSha + ) { + return { status: 'ignored' }; + } const preview = await findPreviousPreview( session ); if ( ! preview ) { - const previous = readPreviewCommentSource( comment.body ); + const previous = commentSource; if ( ! previous ) { return { status: 'unavailable' }; } diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index 3ebe58fd79cc5..15a9c3f917cf9 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -21,13 +21,13 @@ const currentSha = 'a'.repeat( 40 ); const previewSha = 'c'.repeat( 40 ); const snapshotBytes = Buffer.from( 'snapshot' ); -function pullRequest( state = 'open', labels = [] ) { +function pullRequest( state = 'open', labels = [], headSha = currentSha ) { return { number: 123, state, base: { ref: 'trunk' }, head: { - sha: currentSha, + sha: headSha, ref: 'feature', repo: { full_name: sourceRepository }, }, @@ -35,8 +35,12 @@ function pullRequest( state = 'open', labels = [] ) { }; } -function event( action, state = action === 'closed' ? 'closed' : 'open' ) { - return { action, pull_request: pullRequest( state ) }; +function event( + action, + state = action === 'closed' ? 'closed' : 'open', + headSha = currentSha +) { + return { action, pull_request: pullRequest( state, [], headSha ) }; } function previewMetadata() { @@ -240,6 +244,38 @@ test( 'a newer terminal comment supersedes an older stale event', async () => { assert.equal( api.commentBodies.length, 0 ); } ); +test( 'a delayed stale event ignores the current terminal comment', async () => { + const api = new FakeApi(); + api.comment.body = renderPreviewComment( { + status: 'failed', + sourceRepository, + sourceSha: currentSha, + at: '2026-08-09T13:00:00.000Z', + runUrl: `https://github.com/${ repository }/actions/runs/456`, + previous: previewMetadata(), + } ); + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) + ); + assert.equal( result.status, 'ignored' ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 'returning to a stale preview SHA refreshes obsolete visible state', async () => { + const api = new FakeApi(); + installPreview( api ); + await managePullRequest( options( api, event( 'synchronize' ) ) ); + assert.match( api.comment.body, new RegExp( currentSha ) ); + + api.currentPullRequest = pullRequest( 'open', [], previewSha ); + const result = await managePullRequest( + options( api, event( 'synchronize', 'open', previewSha ) ) + ); + assert.equal( result.status, 'stale' ); + assert.doesNotMatch( api.comment.body, new RegExp( currentSha ) ); + assert.match( api.comment.body, new RegExp( previewSha ) ); +} ); + test( 'a stale failed attempt still tells the maintainer how to rebuild', async () => { const api = new FakeApi(); api.comment.body = renderPreviewComment( { diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs index ba905833445e7..464fb42c9d88e 100644 --- a/.github/scripts/docs-playground-preview/test/publisher.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -284,6 +284,10 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { assert.match( stale, /add the `docs-preview` label again/i ); assert.match( stale, new RegExp( sha ) ); assert.match( stale, new RegExp( 'c'.repeat( 40 ) ) ); + assert.deepEqual( readPreviewCommentSource( stale ), { + repository: preview.sourceRepository, + sha, + } ); const unavailable = renderPreviewComment( { status: 'stale-unavailable', previousRepository: preview.sourceRepository, From 7cc50769f14dc1b93da2e8d31bae989d5c4dd6fb Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 15:37:56 +0400 Subject: [PATCH 34/59] Build/Test Tools: Preserve the last docs preview link A shared proxy failure made previous-preview discovery return nothing. Failure reporting then erased the last successful link even though its assets remained. Recover only the publisher-rendered link and source identity from the existing bot comment. A candidate failure must report the failure without making the previous preview unavailable. --- .../docs-playground-preview/lib/publisher.mjs | 26 ++++++++ .../docs-playground-preview/publish.mjs | 9 ++- .../test/publish.test.mjs | 59 ++++++++++++++++++- .../test/publisher.test.mjs | 11 ++++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs index 99d7a450e4d87..22e87dfb29f71 100644 --- a/.github/scripts/docs-playground-preview/lib/publisher.mjs +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -281,6 +281,32 @@ export function readPreviewCommentSource( body ) { return match ? { repository: match[ 1 ], sha: match[ 2 ] } : null; } +export function readPreviewCommentSuccess( body ) { + if ( typeof body !== 'string' ) { + return null; + } + const link = body.match( + /\[(?:Open Code Reference preview|Latest successful docs preview)\]\((https:\/\/playground\.wordpress\.net\/[^\s)]+)\)/ + ); + if ( ! link ) { + return null; + } + const previousSource = body.match( + /Latest successful docs preview\]\([^)]+\) — built from \[([0-9a-f]{40})\]\(https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\/commit\/\1\)/ + ); + const source = previousSource + ? { repository: previousSource[ 2 ], sha: previousSource[ 1 ] } + : readPreviewCommentSource( body ); + if ( ! source ) { + return null; + } + return { + sourceRepository: source.repository, + sourceSha: source.sha, + publication: { playgroundUrl: link[ 1 ] }, + }; +} + export function renderPreviewComment( state ) { if ( state.status === 'ready' ) { const header = commentHeader( { diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 65672e0554ba1..2768bac75998c 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -9,6 +9,7 @@ import { assertLatestAuthorized, createPublishedMetadata, inspectHandoff, + readPreviewCommentSuccess, renderPreviewComment, validateCandidateFile, validatePublicationContext, @@ -152,7 +153,13 @@ async function runIndependently( operations, message ) { } async function reportFailure( session, excluded = new Set() ) { - const previous = await findPreviousPreview( session, excluded ); + let previous = await findPreviousPreview( session, excluded ); + if ( ! previous ) { + const comment = await session.api.findPreviewComment( + session.context.pullRequestNumber + ); + previous = readPreviewCommentSuccess( comment?.body ); + } const body = renderPreviewComment( { status: 'failed', sourceRepository: session.context.sourceRepository, diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index db94c1e4c536e..853057440030c 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -5,7 +5,10 @@ import os from 'node:os'; import path from 'node:path'; import { test } from 'node:test'; -import { createPublishedMetadata } from '../lib/publisher.mjs'; +import { + createPublishedMetadata, + renderPreviewComment, +} from '../lib/publisher.mjs'; import { PLAYGROUND_ORIGIN, createReuseHandoff, @@ -375,6 +378,60 @@ test( 'public delivery failure keeps the previous healthy preview', async () => assert.match( api.comments[ 0 ].body, new RegExp( 'c'.repeat( 40 ) ) ); } ); +test( 'a proxy outage cannot remove the previous comment link', async () => { + const api = new FakeApi(); + const oldBytes = Buffer.from( 'old snapshot' ); + const oldBuild = buildMetadata( { + sourceSha: 'c'.repeat( 40 ), + workflowRunId: '300', + runUrl: `https://github.com/${ repository }/actions/runs/300`, + snapshotFilename: snapshotAssetName( { + pullRequestNumber: 123, + sourceSha: 'c'.repeat( 40 ), + workflowRunId: 300, + workflowRunAttempt: 1, + } ), + snapshotBytes: oldBytes.byteLength, + snapshotSha256: createHash( 'sha256' ) + .update( oldBytes ) + .digest( 'hex' ), + } ); + const oldPreview = installPublishedPreview( api, oldBuild, oldBytes ); + api.comments = [ + { + id: 1, + body: renderPreviewComment( { + status: 'ready', + preview: oldPreview, + runUrl: oldBuild.runUrl, + } ), + }, + ]; + + const current = buildMetadata(); + const directory = await handoffDirectory( current ); + await assert.rejects( + publishPullRequest( + options( api, directory, { + fetchImplementation: publicFetch( + api, + new Set( [ + oldBuild.snapshotFilename, + current.snapshotFilename, + ] ) + ), + } ) + ), + /digest/ + ); + assert.match( api.comments[ 0 ].body, /Latest attempt failed/ ); + assert.match( api.comments[ 0 ].body, /Latest successful docs preview/ ); + assert.match( api.comments[ 0 ].body, new RegExp( 'c'.repeat( 40 ) ) ); + assert.ok( + api.comments[ 0 ].body.includes( oldPreview.publication.playgroundUrl ) + ); +} ); + test( 'a retry cannot delete a same-name preview it did not upload', async () => { const api = new FakeApi(); const current = buildMetadata(); diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs index 464fb42c9d88e..a90dceeeeb5f2 100644 --- a/.github/scripts/docs-playground-preview/test/publisher.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -9,6 +9,7 @@ import { assertLatestAuthorized, createPublishedMetadata, inspectHandoff, + readPreviewCommentSuccess, readPreviewCommentSource, renderPreviewComment, validateCandidateFile, @@ -261,6 +262,11 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { repository: preview.sourceRepository, sha, } ); + assert.deepEqual( readPreviewCommentSuccess( ready ), { + sourceRepository: preview.sourceRepository, + sourceSha: sha, + publication: { playgroundUrl: preview.publication.playgroundUrl }, + } ); assert.equal( ready.match( /Open Code Reference preview/g ).length, 1 ); const failed = renderPreviewComment( { @@ -273,6 +279,11 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { } ); assert.match( failed, /Latest attempt failed/ ); assert.equal( failed.match( /Latest successful docs preview/g ).length, 1 ); + assert.deepEqual( readPreviewCommentSuccess( failed ), { + sourceRepository: preview.sourceRepository, + sourceSha: sha, + publication: { playgroundUrl: preview.publication.playgroundUrl }, + } ); const stale = renderPreviewComment( { status: 'stale', From 44342ea22b6ad96f50f5cfb7c6c0a8e7fb49c545 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 21:11:53 +0400 Subject: [PATCH 35/59] Build/Test Tools: Let Playground choose validation workers The validator forced one worker even though the pinned CLI warns that low worker counts can deadlock on file locks. A ready server could then stop answering health checks and invalidate every snapshot. Use the CLI default and lock that command line down. --- .../docs-playground-preview/lib/validate.mjs | 46 +++++++++++-------- .../test/validate.test.mjs | 18 ++++++++ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs index be2c745bc6be0..5f99e443a0db8 100644 --- a/.github/scripts/docs-playground-preview/lib/validate.mjs +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -62,6 +62,30 @@ function startServer( command, args ) { return { child, closed, output: () => output }; } +export function createValidationServerArguments( + inputs, + blueprint, + baseUrl, + port +) { + return [ + 'server', + '--php', + inputs.dependencies.playground.phpVersion, + '--wp', + inputs.wordpress.version, + '--blueprint', + blueprint, + '--blueprint-may-read-adjacent-files', + '--site-url', + baseUrl, + '--port', + String( port ), + '--verbosity', + 'normal', + ]; +} + async function stopServer( server ) { if ( server.child.exitCode !== null || server.child.signalCode !== null ) { return; @@ -119,24 +143,10 @@ async function withPlaygroundServer( inputs, options, inspect ) { ); const port = await availablePort(); const baseUrl = `http://127.0.0.1:${ port }`; - const server = startServer( options.playgroundCli, [ - 'server', - '--php', - inputs.dependencies.playground.phpVersion, - '--wp', - inputs.wordpress.version, - '--blueprint', - blueprint, - '--blueprint-may-read-adjacent-files', - '--site-url', - baseUrl, - '--port', - String( port ), - '--workers', - '1', - '--verbosity', - 'normal', - ] ); + const server = startServer( + options.playgroundCli, + createValidationServerArguments( inputs, blueprint, baseUrl, port ) + ); try { await waitForBoot( baseUrl, server, options.fetchImplementation ); return await inspect( baseUrl ); diff --git a/.github/scripts/docs-playground-preview/test/validate.test.mjs b/.github/scripts/docs-playground-preview/test/validate.test.mjs index 26735746d4c3b..e108716d85fa4 100644 --- a/.github/scripts/docs-playground-preview/test/validate.test.mjs +++ b/.github/scripts/docs-playground-preview/test/validate.test.mjs @@ -3,6 +3,7 @@ import { test } from 'node:test'; import { createValidationBlueprint, + createValidationServerArguments, inspectSnapshotBehavior, validateSnapshot, } from '../lib/validate.mjs'; @@ -119,6 +120,23 @@ test( 'validation Blueprint boots the exact snapshot without login or networking ] ); } ); +test( 'validation server uses the pinned Playground worker default', () => { + const args = createValidationServerArguments( + inputs(), + '/tmp/validation-blueprint.json', + 'http://127.0.0.1:9400', + 9400 + ); + assert.equal( args.includes( '--workers' ), false ); + assert.deepEqual( args.slice( 0, 5 ), [ + 'server', + '--php', + '8.4', + '--wp', + '7.2-beta1', + ] ); +} ); + test( 'behavioral validation covers health, routes, search, and banner', async () => { const result = await inspectSnapshotBehavior( inputs(), { baseUrl: 'http://127.0.0.1:9400', From 82c01efe64b4c0a8b6ca9682cf2ae37d057a18ee Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 22:04:14 +0400 Subject: [PATCH 36/59] Build/Test Tools: Use six Playground snapshot workers GitHub exposes four CPUs, so Playground selected three workers and exported a malformed SQLite database in both staging builds. Invoke the pinned programmatic API with its recommended six workers and validate with the same count. If this is wrong, every reference route dies with a database error. --- .../docs-playground-preview/lib/base.mjs | 24 +++++-------- .../docs-playground-preview/lib/final.mjs | 36 ++++++++----------- .../lib/playground.mjs | 21 +++++++++++ .../docs-playground-preview/lib/validate.mjs | 4 +++ .../test/final.test.mjs | 19 +++++----- .../test/playground.test.mjs | 28 +++++++++++++++ .../test/validate.test.mjs | 4 +-- 7 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/lib/playground.mjs create mode 100644 .github/scripts/docs-playground-preview/test/playground.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/base.mjs b/.github/scripts/docs-playground-preview/lib/base.mjs index 88bfab55e9db6..b21ee0f7f517f 100644 --- a/.github/scripts/docs-playground-preview/lib/base.mjs +++ b/.github/scripts/docs-playground-preview/lib/base.mjs @@ -4,6 +4,7 @@ import path from 'node:path'; import { copyDirectory, downloadFile, zipDirectory } from './archive.mjs'; import { acquireRepositories, exists } from './files.mjs'; +import { buildSnapshot } from './playground.mjs'; import { run } from './process.mjs'; const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); @@ -279,23 +280,16 @@ async function buildInvariantBase( inputs, options ) { 2 ) }\n` ); - await runImplementation( + await ( options.buildSnapshotImplementation || buildSnapshot )( options.playgroundCli || executable( 'wp-playground-cli' ), - [ - 'build-snapshot', - '--php', - inputs.dependencies.playground.phpVersion, - '--wp', - inputs.wordpress.version, - '--blueprint', + { + php: inputs.dependencies.playground.phpVersion, + wp: inputs.wordpress.version, blueprint, - '--blueprint-may-read-adjacent-files', - '--outfile', - path.join( inputs.cacheDirectory, 'base.zip' ), - '--verbosity', - 'normal', - ], - { label: 'build invariant Playground base' } + 'blueprint-may-read-adjacent-files': true, + outfile: path.join( inputs.cacheDirectory, 'base.zip' ), + verbosity: 'normal', + } ); await copyDirectory( roots.phpdocParser, diff --git a/.github/scripts/docs-playground-preview/lib/final.mjs b/.github/scripts/docs-playground-preview/lib/final.mjs index cffa6a8d145dd..a9816b8e5314c 100644 --- a/.github/scripts/docs-playground-preview/lib/final.mjs +++ b/.github/scripts/docs-playground-preview/lib/final.mjs @@ -3,7 +3,7 @@ import { fileURLToPath } from 'node:url'; import path from 'node:path'; import { sha256File } from './files.mjs'; -import { run } from './process.mjs'; +import { buildSnapshot } from './playground.mjs'; import { renderRuntimePlugin } from './runtime.mjs'; const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); @@ -92,7 +92,6 @@ export function createFinalBlueprint( inputs ) { } export async function packageFinalSnapshot( inputs, options ) { - const runImplementation = options.runImplementation || run; const work = path.resolve( options.workDirectory ); const output = path.resolve( options.output ); await rm( work, { recursive: true, force: true } ); @@ -123,27 +122,22 @@ export async function packageFinalSnapshot( inputs, options ) { blueprint, `${ JSON.stringify( createFinalBlueprint( inputs ), null, 2 ) }\n` ); - await runImplementation( + await ( options.buildSnapshotImplementation || buildSnapshot )( options.playgroundCli, - [ - 'build-snapshot', - '--php', - inputs.dependencies.playground.phpVersion, - '--wp', - inputs.wordpress.version, - '--blueprint', + { + php: inputs.dependencies.playground.phpVersion, + wp: inputs.wordpress.version, blueprint, - '--blueprint-may-read-adjacent-files', - '--mount', - `${ path.resolve( - options.stagedSource - ) }:/tmp/docs-preview-source`, - '--outfile', - output, - '--verbosity', - 'normal', - ], - { label: 'build final Code Reference snapshot' } + 'blueprint-may-read-adjacent-files': true, + mount: [ + { + hostPath: path.resolve( options.stagedSource ), + vfsPath: '/tmp/docs-preview-source', + }, + ], + outfile: output, + verbosity: 'normal', + } ); const snapshot = await stat( output ); if ( snapshot.size > inputs.dependencies.limits.snapshotBytes ) { diff --git a/.github/scripts/docs-playground-preview/lib/playground.mjs b/.github/scripts/docs-playground-preview/lib/playground.mjs new file mode 100644 index 0000000000000..a2958e815915f --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/playground.mjs @@ -0,0 +1,21 @@ +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; + +export const PLAYGROUND_WORKERS = 6; + +export function createSnapshotArguments( options ) { + return { + ...options, + command: 'build-snapshot', + workers: PLAYGROUND_WORKERS, + }; +} + +export async function buildSnapshot( playgroundCli, options ) { + const modulePath = path.resolve( + path.dirname( playgroundCli ), + '../@wp-playground/cli/index.js' + ); + const { runCLI } = await import( pathToFileURL( modulePath ) ); + await runCLI( createSnapshotArguments( options ) ); +} diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs index 5f99e443a0db8..b46a16bfc21e0 100644 --- a/.github/scripts/docs-playground-preview/lib/validate.mjs +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -3,6 +3,8 @@ import { copyFile, mkdir, rm, writeFile } from 'node:fs/promises'; import { createServer } from 'node:net'; import path from 'node:path'; +import { PLAYGROUND_WORKERS } from './playground.mjs'; + const BANNER_ID = 'wporg-code-reference-preview-provenance'; function bundled( resourcePath ) { @@ -81,6 +83,8 @@ export function createValidationServerArguments( baseUrl, '--port', String( port ), + '--workers', + String( PLAYGROUND_WORKERS ), '--verbosity', 'normal', ]; diff --git a/.github/scripts/docs-playground-preview/test/final.test.mjs b/.github/scripts/docs-playground-preview/test/final.test.mjs index a18ffa40afb50..c6cead429d0fe 100644 --- a/.github/scripts/docs-playground-preview/test/final.test.mjs +++ b/.github/scripts/docs-playground-preview/test/final.test.mjs @@ -94,8 +94,8 @@ async function fixture( snapshotBytes = 1024 ) { test( 'final packaging returns publisher metadata for a bounded snapshot', async () => { const current = await fixture(); let invocation; - const runImplementation = async ( command, args ) => { - invocation = { command, args }; + const buildSnapshotImplementation = async ( command, options ) => { + invocation = { command, options }; await writeFile( current.output, 'snapshot' ); }; const snapshot = await packageFinalSnapshot( current.resolved, { @@ -110,16 +110,17 @@ test( 'final packaging returns publisher metadata for a bounded snapshot', async generationTimestamp: '2026-08-09T12:34:56.000Z', runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', }, - runImplementation, + buildSnapshotImplementation, } ); assert.equal( snapshot.filename, 'snapshot.zip' ); assert.equal( snapshot.bytes, 8 ); assert.match( snapshot.sha256, /^[0-9a-f]{64}$/ ); assert.equal( invocation.command, '/tools/wp-playground-cli' ); - assert.equal( - invocation.args[ invocation.args.indexOf( '--mount' ) + 1 ], - '/source:/tmp/docs-preview-source' - ); + assert.deepEqual( invocation.options.mount, [ + { hostPath: '/source', vfsPath: '/tmp/docs-preview-source' }, + ] ); + assert.equal( invocation.options.php, '8.4' ); + assert.equal( invocation.options.wp, '7.2-beta1' ); const blueprint = JSON.parse( await readFile( path.join( current.root, 'work/final-blueprint.json' ), @@ -131,7 +132,7 @@ test( 'final packaging returns publisher metadata for a bounded snapshot', async test( 'the 100 MiB snapshot boundary always fails closed', async () => { const current = await fixture( 8 ); - const runImplementation = async () => { + const buildSnapshotImplementation = async () => { const output = await open( current.output, 'w' ); await output.truncate( 9 ); await output.close(); @@ -149,7 +150,7 @@ test( 'the 100 MiB snapshot boundary always fails closed', async () => { generationTimestamp: '2026-08-09T12:34:56.000Z', runUrl: 'https://github.com/example/wordpress-develop/actions/runs/123', }, - runImplementation, + buildSnapshotImplementation, } ), /exceeds 100 MiB/ ); diff --git a/.github/scripts/docs-playground-preview/test/playground.test.mjs b/.github/scripts/docs-playground-preview/test/playground.test.mjs new file mode 100644 index 0000000000000..72380a7f7afa1 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/playground.test.mjs @@ -0,0 +1,28 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; + +import { + createSnapshotArguments, + PLAYGROUND_WORKERS, +} from '../lib/playground.mjs'; + +test( 'snapshot builds use six Playground workers', () => { + assert.deepEqual( + createSnapshotArguments( { + php: '8.4', + wp: '7.2-beta1', + blueprint: '/tmp/blueprint.json', + outfile: '/tmp/snapshot.zip', + workers: 2, + command: 'server', + } ), + { + php: '8.4', + wp: '7.2-beta1', + blueprint: '/tmp/blueprint.json', + outfile: '/tmp/snapshot.zip', + workers: PLAYGROUND_WORKERS, + command: 'build-snapshot', + } + ); +} ); diff --git a/.github/scripts/docs-playground-preview/test/validate.test.mjs b/.github/scripts/docs-playground-preview/test/validate.test.mjs index e108716d85fa4..df3836fd09c3c 100644 --- a/.github/scripts/docs-playground-preview/test/validate.test.mjs +++ b/.github/scripts/docs-playground-preview/test/validate.test.mjs @@ -120,14 +120,14 @@ test( 'validation Blueprint boots the exact snapshot without login or networking ] ); } ); -test( 'validation server uses the pinned Playground worker default', () => { +test( 'validation server uses six Playground workers', () => { const args = createValidationServerArguments( inputs(), '/tmp/validation-blueprint.json', 'http://127.0.0.1:9400', 9400 ); - assert.equal( args.includes( '--workers' ), false ); + assert.equal( args[ args.indexOf( '--workers' ) + 1 ], '6' ); assert.deepEqual( args.slice( 0, 5 ), [ 'server', '--php', From ced22400617afb9c04d97ddfd96b7d4e145b5dff Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 22:59:44 +0400 Subject: [PATCH 37/59] Build/Test Tools: Serialize Playground snapshot builds Playground exports a live filesystem after running the Blueprint. Multiple build workers left SQLite corrupt after the full reference import. Build with one worker, then boot the finished snapshot with six. If this regresses, every reference route dies before publication. --- .github/scripts/docs-playground-preview/lib/playground.mjs | 5 +++-- .github/scripts/docs-playground-preview/lib/validate.mjs | 4 ++-- .../docs-playground-preview/test/playground.test.mjs | 7 ++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/playground.mjs b/.github/scripts/docs-playground-preview/lib/playground.mjs index a2958e815915f..0fbc15e8231d8 100644 --- a/.github/scripts/docs-playground-preview/lib/playground.mjs +++ b/.github/scripts/docs-playground-preview/lib/playground.mjs @@ -1,13 +1,14 @@ import path from 'node:path'; import { pathToFileURL } from 'node:url'; -export const PLAYGROUND_WORKERS = 6; +export const PLAYGROUND_BUILD_WORKERS = 1; +export const PLAYGROUND_SERVER_WORKERS = 6; export function createSnapshotArguments( options ) { return { ...options, command: 'build-snapshot', - workers: PLAYGROUND_WORKERS, + workers: PLAYGROUND_BUILD_WORKERS, }; } diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs index b46a16bfc21e0..0e23b74433263 100644 --- a/.github/scripts/docs-playground-preview/lib/validate.mjs +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -3,7 +3,7 @@ import { copyFile, mkdir, rm, writeFile } from 'node:fs/promises'; import { createServer } from 'node:net'; import path from 'node:path'; -import { PLAYGROUND_WORKERS } from './playground.mjs'; +import { PLAYGROUND_SERVER_WORKERS } from './playground.mjs'; const BANNER_ID = 'wporg-code-reference-preview-provenance'; @@ -84,7 +84,7 @@ export function createValidationServerArguments( '--port', String( port ), '--workers', - String( PLAYGROUND_WORKERS ), + String( PLAYGROUND_SERVER_WORKERS ), '--verbosity', 'normal', ]; diff --git a/.github/scripts/docs-playground-preview/test/playground.test.mjs b/.github/scripts/docs-playground-preview/test/playground.test.mjs index 72380a7f7afa1..ba6e04aa5c206 100644 --- a/.github/scripts/docs-playground-preview/test/playground.test.mjs +++ b/.github/scripts/docs-playground-preview/test/playground.test.mjs @@ -3,10 +3,11 @@ import { test } from 'node:test'; import { createSnapshotArguments, - PLAYGROUND_WORKERS, + PLAYGROUND_BUILD_WORKERS, } from '../lib/playground.mjs'; -test( 'snapshot builds use six Playground workers', () => { +test( 'snapshot builds serialize Playground filesystem access', () => { + assert.equal( PLAYGROUND_BUILD_WORKERS, 1 ); assert.deepEqual( createSnapshotArguments( { php: '8.4', @@ -21,7 +22,7 @@ test( 'snapshot builds use six Playground workers', () => { wp: '7.2-beta1', blueprint: '/tmp/blueprint.json', outfile: '/tmp/snapshot.zip', - workers: PLAYGROUND_WORKERS, + workers: PLAYGROUND_BUILD_WORKERS, command: 'build-snapshot', } ); From 6344e3fd1b09466409ce7a74c0ca170c02b02f8b Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Sun, 9 Aug 2026 23:39:56 +0400 Subject: [PATCH 38/59] Build/Test Tools: Preserve ambiguous trunk assets GitHub can expose a stale ref immediately after creating the stable pointer. Treating that read as proof of failure deleted the assets the new pointer named. Any unconfirmed mutation now retains both generations; the next successful publication cleans the orphan. --- .../docs-playground-preview/publish-trunk.mjs | 6 ++- .../test/publish-trunk.test.mjs | 43 +++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index 3ddd97bb134af..e7c942c5bc2df 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -203,7 +203,11 @@ async function moveStablePointer( session, previousRef, commit, transaction ) { commit.sha ); if ( ! moved ) { - throw mutationError || new Error( 'The trunk pointer did not move.' ); + const error = + mutationError || + new Error( 'The stable trunk pointer mutation has unknown state.' ); + error.pointerStateUnknown = true; + throw error; } transaction.pointerPublished = true; } diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index db1c5df673ad9..9ebd9c089a33b 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -91,6 +91,7 @@ class FakeApi { this.refReads = 0; this.refUpdateFailure = null; this.failRefResolution = false; + this.staleRefAfterMutation = false; } async getRun() { @@ -135,11 +136,15 @@ class FakeApi { async getGitReference( reference ) { assert.equal( reference, TRUNK_POINTER_REF ); this.refReads++; - this.events.push( `git:read-ref:${ this.refSha }` ); + const visibleSha = + this.staleRefAfterMutation && this.refReads > 1 + ? this.previousRefSha + : this.refSha; + this.events.push( `git:read-ref:${ visibleSha }` ); if ( this.failRefResolution && this.refReads > 1 ) { throw new Error( 'ref resolution failed' ); } - return this.refSha ? { object: { sha: this.refSha } } : null; + return visibleSha ? { object: { sha: visibleSha } } : null; } async createGitBlob( content ) { @@ -409,7 +414,7 @@ test( 'public candidate failure leaves the previous pointer and snapshot intact' assert.deepEqual( api.deleted.sort(), [ 10, 11 ] ); } ); -test( 'a failed ref update leaves the previous pointer intact', async () => { +test( 'a failed ref update retains the previous and candidate assets', async () => { const api = new FakeApi(); installPrevious( api ); api.refUpdateFailure = 'before'; @@ -420,7 +425,8 @@ test( 'a failed ref update leaves the previous pointer intact', async () => { ); assert.equal( api.refSha, api.previousRefSha ); assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); - assert.deepEqual( api.deleted.sort(), [ 10, 11 ] ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); + assert.deepEqual( api.deleted, [] ); } ); test( 'an ambiguous ref response resolves the candidate and completes', async () => { @@ -452,6 +458,35 @@ test( 'unresolved ref state retains both valid generations', async () => { assert.deepEqual( api.deleted, [] ); } ); +test( 'a stale read after ref creation retains the candidate assets', async () => { + const api = new FakeApi(); + api.staleRefAfterMutation = true; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( options( api, directory ) ), + /pointer mutation has unknown state/ + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.equal( api.assets.length, 2 ); + assert.deepEqual( api.deleted, [] ); +} ); + +test( 'an update error and stale read retain both asset generations', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.refUpdateFailure = 'after'; + api.staleRefAfterMutation = true; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishTrunk( options( api, directory ) ), + /ref update response failed/ + ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); + assert.deepEqual( api.deleted, [] ); +} ); + test( 'cleanup failure keeps the new validated pointer and both snapshots', async () => { const api = new FakeApi(); installPrevious( api ); From f265b00beca825fbee8f03400135b2f8c7434529 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 07:31:50 +0400 Subject: [PATCH 39/59] Build/Test Tools: Allow staging fork documentation builds Fork pull_request runs do not receive the base repository's Actions variables. The old condition made the required fork lifecycle impossible to exercise in staging.\n\nAllow the hard-coded staging repository to run only the untrusted read-only build. Keep trunk, publication, lifecycle, and cleanup behind DOCS_PREVIEW_STAGING. --- .github/docs-playground-preview/README.md | 6 ++- .../test/config.test.mjs | 40 +++++++++++++++++++ .../docs-playground-preview-build.yml | 5 ++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/.github/docs-playground-preview/README.md b/.github/docs-playground-preview/README.md index 346bcf51a93c3..b699b11dc2d53 100644 --- a/.github/docs-playground-preview/README.md +++ b/.github/docs-playground-preview/README.md @@ -46,9 +46,11 @@ A manifest or harness change automatically produces a different exact cache key. ## Repository activation -The workflows run in `WordPress/wordpress-develop`. They also run in `sirreal/wordpress-develop` only when the repository Actions variable `DOCS_PREVIEW_STAGING` is exactly `true`. They remain inert in every other fork. +The workflows run in `WordPress/wordpress-develop`. Trusted staging work in `sirreal/wordpress-develop` runs only when the repository Actions variable `DOCS_PREVIEW_STAGING` is exactly `true`. That variable controls `trunk` builds, PR and `trunk` publishers, comments, labels, stale and expired lifecycle handling, cleanup, cache deletion, and every other trusted mutation. -The staging repository needs a `docs-preview` label and the Actions variables used for the scenario being tested. Disable staging by deleting `DOCS_PREVIEW_STAGING` or setting it to anything other than the lowercase string `true`. +There is one deliberate staging exception: the untrusted `pull_request` build job is enabled by the hard-coded `sirreal/wordpress-develop` allowlist without consulting `DOCS_PREVIEW_STAGING`. GitHub does not expose the base repository's Actions variables to a fork's `pull_request` workflow run. Requiring the variable there would make the required fork preview impossible to stage. With staging disabled, explicitly labeling a PR may therefore consume isolated read-only CI and create a one-day handoff artifact, but it cannot publish, comment, change labels, delete caches, or perform another trusted mutation. Arbitrary forks remain inert. This user-approved exception to section 5 is confined to the staging repository and the untrusted build job. + +The staging repository needs a `docs-preview` label and the Actions variables used for the scenario being tested. Disable trusted staging by deleting `DOCS_PREVIEW_STAGING` or setting it to anything other than the lowercase string `true`. ## Validation enforcement diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index adcb27fc9e85f..3d00269952c8b 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -21,6 +21,18 @@ const nodeVersionFile = new URL( '../../../docs-playground-preview/.nvmrc', import.meta.url ); +const buildWorkflowFile = new URL( + '../../../workflows/docs-playground-preview-build.yml', + import.meta.url +); +const publishWorkflowFile = new URL( + '../../../workflows/docs-playground-preview-publish.yml', + import.meta.url +); +const lifecycleWorkflowFile = new URL( + '../../../workflows/docs-playground-preview-lifecycle.yml', + import.meta.url +); async function manifest() { return JSON.parse( await readFile( dependenciesFile, 'utf8' ) ); @@ -181,3 +193,31 @@ test( 'deployment is inert outside the primary and opted-in staging repositories false ); } ); + +test( 'only the untrusted staging pull-request build bypasses staging activation', async () => { + const buildWorkflow = await readFile( buildWorkflowFile, 'utf8' ); + const publishWorkflow = await readFile( publishWorkflowFile, 'utf8' ); + const lifecycleWorkflow = await readFile( lifecycleWorkflowFile, 'utf8' ); + const trunkJobOffset = buildWorkflow.indexOf( '\n build-trunk:' ); + + assert.notEqual( trunkJobOffset, -1 ); + assert.match( + buildWorkflow.slice( 0, trunkJobOffset ), + /github\.repository == 'sirreal\/wordpress-develop' / + ); + assert.doesNotMatch( + buildWorkflow.slice( 0, trunkJobOffset ), + /vars\.DOCS_PREVIEW_STAGING/ + ); + + for ( const trustedWorkflow of [ + buildWorkflow.slice( trunkJobOffset ), + publishWorkflow, + lifecycleWorkflow, + ] ) { + assert.match( + trustedWorkflow, + /github\.repository == 'sirreal\/wordpress-develop' && vars\.DOCS_PREVIEW_STAGING == 'true'/ + ); + } +} ); diff --git a/.github/workflows/docs-playground-preview-build.yml b/.github/workflows/docs-playground-preview-build.yml index 5d7a9f1f2cf59..ed311e720e7e8 100644 --- a/.github/workflows/docs-playground-preview-build.yml +++ b/.github/workflows/docs-playground-preview-build.yml @@ -15,10 +15,13 @@ permissions: {} jobs: build: name: Build Code Reference snapshot + # Fork pull_request runs cannot read the base repository's Actions variables. + # This allowlisted job is untrusted and read-only; every trusted staging job + # remains gated by DOCS_PREVIEW_STAGING. if: >- github.event_name == 'pull_request' && ( github.repository == 'WordPress/wordpress-develop' || - ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) && + github.repository == 'sirreal/wordpress-develop' ) && github.event.pull_request.base.ref == 'trunk' && github.event.pull_request.state == 'open' && ( ( github.event.action == 'labeled' && github.event.label.name == 'docs-preview' ) || From 7ff5bd751e9f8b47346db2dde2dd06a805a29fe1 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 07:43:56 +0400 Subject: [PATCH 40/59] Build/Test Tools: Enforce fork preview validation Fork pull_request runs cannot read the base repository's Actions variables. The old check silently left every fork in advisory mode, so DOCS_PREVIEW_ENFORCE did not enforce anything.\n\nApply the exact base-repository value in the trusted publisher after it records the failure and preserves the live preview. --- .github/docs-playground-preview/README.md | 2 ++ .../docs-playground-preview/publish.mjs | 31 +++++++++++++------ .../test/config.test.mjs | 4 +++ .../test/publish.test.mjs | 19 +++++++++++- .../docs-playground-preview-publish.yml | 6 ++++ 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/.github/docs-playground-preview/README.md b/.github/docs-playground-preview/README.md index b699b11dc2d53..56b23b28a4af4 100644 --- a/.github/docs-playground-preview/README.md +++ b/.github/docs-playground-preview/README.md @@ -56,6 +56,8 @@ The staging repository needs a `docs-preview` label and the Actions variables us Behavioral validation is advisory unless the repository Actions variable `DOCS_PREVIEW_ENFORCE` is exactly `true`. Advisory failures emit workflow warnings and terminal PR state but cannot publish or replace a snapshot. Fatal build, handoff, identity, digest, size, and publication failures always fail. +GitHub does not expose base-repository Actions variables to an untrusted fork `pull_request` job. Such a job therefore records a behavioral failure in its handoff without enforcing it locally. The trusted publisher reads `DOCS_PREVIEW_ENFORCE` from the base repository, updates the sticky comment without publishing the invalid candidate, and then fails its workflow when enforcement is enabled. Same-repository and `trunk` builds can read the variable directly and fail their build workflow as well. + To enable enforcement: 1. Open repository **Settings**. diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 2768bac75998c..304ddc1bd3408 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -366,17 +366,30 @@ export async function publishPullRequest( options ) { } } +export function enforceValidationResult( result, enforcementVariable ) { + if ( result.status === 'invalid' && enforcementVariable === 'true' ) { + throw new Error( + 'Code Reference validation failed with DOCS_PREVIEW_ENFORCE enabled.' + ); + } + return result; +} + async function main() { const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); - const result = await publishPullRequest( { - repository: process.env.GITHUB_REPOSITORY, - stagingVariable: process.env.DOCS_PREVIEW_STAGING, - triggerRunId: event.workflow_run.id, - triggerRunAttempt: event.workflow_run.run_attempt, - handoffDirectory: process.argv[ 2 ] || 'handoff', - artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', - token: process.env.GITHUB_TOKEN, - } ); + const result = enforceValidationResult( + await publishPullRequest( { + repository: process.env.GITHUB_REPOSITORY, + stagingVariable: process.env.DOCS_PREVIEW_STAGING, + triggerRunId: event.workflow_run.id, + triggerRunAttempt: event.workflow_run.run_attempt, + handoffDirectory: process.argv[ 2 ] || 'handoff', + artifactAvailable: + process.env.HANDOFF_DOWNLOAD_RESULT === 'success', + token: process.env.GITHUB_TOKEN, + } ), + process.env.DOCS_PREVIEW_ENFORCE + ); process.stdout.write( `Code Reference publisher: ${ result.status }.\n` ); } diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 3d00269952c8b..27c6c06e4c1b8 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -220,4 +220,8 @@ test( 'only the untrusted staging pull-request build bypasses staging activation /github\.repository == 'sirreal\/wordpress-develop' && vars\.DOCS_PREVIEW_STAGING == 'true'/ ); } + assert.match( + publishWorkflow, + /DOCS_PREVIEW_ENFORCE: \$\{\{ vars\.DOCS_PREVIEW_ENFORCE \}\}/ + ); } ); diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index 853057440030c..5d7ceab6d9b3a 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -16,7 +16,10 @@ import { releaseAssetUrl, snapshotAssetName, } from '../lib/publication.mjs'; -import { publishPullRequest } from '../publish.mjs'; +import { + enforceValidationResult, + publishPullRequest, +} from '../publish.mjs'; const repository = 'WordPress/wordpress-develop'; const sourceRepository = 'contributor/wordpress-develop'; @@ -301,6 +304,20 @@ test( 'an advisory validation failure updates the comment but publishes nothing' assert.equal( api.labelRemovals, 1 ); } ); +test( 'the trusted publisher enforces invalid fork handoffs', () => { + const invalid = { status: 'invalid' }; + assert.throws( + () => enforceValidationResult( invalid, 'true' ), + /DOCS_PREVIEW_ENFORCE/ + ); + assert.equal( enforceValidationResult( invalid, 'false' ), invalid ); + assert.equal( enforceValidationResult( invalid, 'TRUE' ), invalid ); + assert.equal( + enforceValidationResult( { status: 'ready' }, 'true' ).status, + 'ready' + ); +} ); + test( 'a missing handoff always fails after its terminal comment', async () => { const api = new FakeApi(); const directory = await mkdtemp( diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index 97e48c1c41953..06086b100affd 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -54,7 +54,13 @@ jobs: digest-mismatch: error - name: Validate and publish the handoff + # Fork pull_request jobs cannot read the base repository's Actions + # variables. The trusted publisher therefore applies enforcement + # after reporting the invalid candidate and preserving the live link. + # Administrator: enable enforcement in Settings > Secrets and variables > + # Actions > Variables by creating or updating DOCS_PREVIEW_ENFORCE to true. env: + DOCS_PREVIEW_ENFORCE: ${{ vars.DOCS_PREVIEW_ENFORCE }} DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} GITHUB_TOKEN: ${{ github.token }} HANDOFF_DOWNLOAD_RESULT: ${{ steps.download.outcome }} From ae69eb61cbf70bf3529d70d765295a02624d798c Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 08:14:46 +0400 Subject: [PATCH 41/59] Build/Test Tools: Report nested publisher failures The publisher collapsed multiple failures into an AggregateError and discarded every cause. That leaves a broken comment or label path with no actionable log.\n\nPrint the nested causes after the transaction has already failed. Publication behavior and exit status stay unchanged. --- .../docs-playground-preview/publish.mjs | 16 +++++++++++++- .../test/publish.test.mjs | 22 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 304ddc1bd3408..3a7cfd92496fe 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -19,6 +19,20 @@ import { findPreviousPreview, loadPublishedPreview } from './lib/published.mjs'; class SupersededRun extends Error {} +export function formatFailure( error ) { + const description = error.stack || String( error ); + if ( ! ( error instanceof AggregateError ) ) { + return description; + } + return [ + description, + ...error.errors.map( + ( cause, index ) => + `Cause ${ index + 1 }:\n${ formatFailure( cause ) }` + ), + ].join( '\n' ); +} + async function readHandoff( directory ) { return JSON.parse( await readFile( path.join( directory, 'build.json' ), 'utf8' ) @@ -395,7 +409,7 @@ async function main() { if ( import.meta.url === pathToFileURL( process.argv[ 1 ] ).href ) { main().catch( ( error ) => { - process.stderr.write( `${ error.stack || error }\n` ); + process.stderr.write( `${ formatFailure( error ) }\n` ); process.exitCode = 1; } ); } diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index 5d7ceab6d9b3a..123ed316d3fa2 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -18,6 +18,7 @@ import { } from '../lib/publication.mjs'; import { enforceValidationResult, + formatFailure, publishPullRequest, } from '../publish.mjs'; @@ -318,6 +319,27 @@ test( 'the trusted publisher enforces invalid fork handoffs', () => { ); } ); +test( 'publisher failures retain every nested cause in the Actions log', () => { + const failure = new AggregateError( + [ + new Error( 'candidate upload failed' ), + new AggregateError( + [ + new Error( 'comment failed' ), + new Error( 'label removal failed' ), + ], + 'failure reporting failed' + ), + ], + 'publication failed' + ); + const formatted = formatFailure( failure ); + + assert.match( formatted, /candidate upload failed/ ); + assert.match( formatted, /comment failed/ ); + assert.match( formatted, /label removal failed/ ); +} ); + test( 'a missing handoff always fails after its terminal comment', async () => { const api = new FakeApi(); const directory = await mkdtemp( From e438fd8cb666435d1ac3c15a0db29607e20536ad Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 08:18:54 +0400 Subject: [PATCH 42/59] Build/Test Tools: Grant PR publisher write access The trusted publisher could upload snapshots but GitHub rejected every PR comment and label mutation. Declaring pull requests read-only made the required lifecycle impossible.\n\nGrant write access to pull requests and drop the redundant issue scope. The trunk publisher remains unchanged. --- .../docs-playground-preview/test/config.test.mjs | 13 +++++++++++++ .../workflows/docs-playground-preview-publish.yml | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 27c6c06e4c1b8..25ad9a0c1690b 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -224,4 +224,17 @@ test( 'only the untrusted staging pull-request build bypasses staging activation publishWorkflow, /DOCS_PREVIEW_ENFORCE: \$\{\{ vars\.DOCS_PREVIEW_ENFORCE \}\}/ ); + const trunkPublisherOffset = publishWorkflow.indexOf( + '\n publish-trunk:' + ); + assert.notEqual( trunkPublisherOffset, -1 ); + const pullRequestPublisher = publishWorkflow.slice( + 0, + trunkPublisherOffset + ); + assert.match( + pullRequestPublisher, + /publish:\n[\s\S]*?permissions:\n[\s\S]*?pull-requests: write/ + ); + assert.doesNotMatch( pullRequestPublisher, /issues: write/ ); } ); diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index 06086b100affd..49c4029a2c9da 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -27,8 +27,7 @@ jobs: permissions: actions: read contents: write - issues: write - pull-requests: read + pull-requests: write steps: - name: Check out trusted default-branch publisher code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 From 6f3f9318f329063aeee7dcfb0dee5c334fba2293 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 09:42:31 +0400 Subject: [PATCH 43/59] Build/Test Tools: Preserve stale docs preview links Stale lifecycle work discarded the last working link when public revalidation was temporarily unavailable. Its token also used a different PR write scope than the publisher. Reuse the marked comment's last-successful identity as the fallback and grant the same pull-request write permission. A proxy outage now leaves the working preview reachable while the comment moves to Stale. --- .../docs-playground-preview/lifecycle.mjs | 6 +++++- .../test/config.test.mjs | 5 +++++ .../test/lifecycle.test.mjs | 21 +++++++++++++++++++ .../docs-playground-preview-lifecycle.yml | 6 ++---- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index c0110077933cf..1daf868ac6e6a 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -7,6 +7,7 @@ import { isDeploymentEnabled } from './lib/config.mjs'; import { GitHubApi } from './lib/github.mjs'; import { findPreviousPreview } from './lib/published.mjs'; import { + readPreviewCommentSuccess, readPreviewCommentSource, renderPreviewComment, } from './lib/publisher.mjs'; @@ -159,7 +160,10 @@ async function markStale( session ) { ) { return { status: 'ignored' }; } - const preview = await findPreviousPreview( session ); + let preview = await findPreviousPreview( session ); + if ( ! preview ) { + preview = readPreviewCommentSuccess( comment.body ); + } if ( ! preview ) { const previous = commentSource; if ( ! previous ) { diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 25ad9a0c1690b..3b43da2b2e364 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -237,4 +237,9 @@ test( 'only the untrusted staging pull-request build bypasses staging activation /publish:\n[\s\S]*?permissions:\n[\s\S]*?pull-requests: write/ ); assert.doesNotMatch( pullRequestPublisher, /issues: write/ ); + assert.equal( + lifecycleWorkflow.match( /pull-requests: write/g )?.length, + 2 + ); + assert.doesNotMatch( lifecycleWorkflow, /issues: write/ ); } ); diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index 15a9c3f917cf9..ac5c63dc9f2ed 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -211,6 +211,27 @@ test( 'a later unlabeled commit marks the healthy preview stale', async () => { assert.match( api.comment.body, /add the `docs-preview` label again/i ); } ); +test( 'a proxy outage cannot remove the last successful stale link', async () => { + const api = new FakeApi(); + const preview = installPreview( api ); + api.comment.body = renderPreviewComment( { + status: 'ready', + preview, + runUrl: preview.runUrl, + } ); + const lifecycleOptions = options( api, event( 'synchronize' ) ); + lifecycleOptions.fetchImplementation = async () => ( { status: 503 } ); + + const result = await managePullRequest( lifecycleOptions ); + + assert.equal( result.status, 'stale' ); + assert.match( api.comment.body, /Status:\*\* Stale/ ); + assert.match( api.comment.body, /Latest successful docs preview/ ); + assert.ok( api.comment.body.includes( preview.publication.playgroundUrl ) ); + assert.match( api.comment.body, new RegExp( previewSha ) ); + assert.match( api.comment.body, new RegExp( currentSha ) ); +} ); + test( 'a labeled synchronize event leaves the publisher in charge', async () => { const api = new FakeApi(); api.currentPullRequest = pullRequest( 'open', [ diff --git a/.github/workflows/docs-playground-preview-lifecycle.yml b/.github/workflows/docs-playground-preview-lifecycle.yml index 1bb0a238319c4..fb7f7f0cbdc3f 100644 --- a/.github/workflows/docs-playground-preview-lifecycle.yml +++ b/.github/workflows/docs-playground-preview-lifecycle.yml @@ -25,8 +25,7 @@ jobs: permissions: actions: read contents: read - issues: write - pull-requests: read + pull-requests: write steps: - name: Check out trusted default-branch lifecycle code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -76,8 +75,7 @@ jobs: permissions: actions: write contents: write - issues: write - pull-requests: read + pull-requests: write steps: - name: Check out trusted default-branch lifecycle code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 From 000d9f8559609e111c2c97bc8008b00c4f89edc5 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 12:56:27 +0400 Subject: [PATCH 44/59] Build/Test Tools: Resolve stable builds between betas Preview builds resolve WordPress from the beta channel and fail outright when that channel offers no beta or release candidate. Every labeled pull request build and every trunk build therefore breaks for the weeks between a stable release and the next beta, and the pinned channel leaves no configuration escape. Fall back to the stable offer from the same version check response, keeping the strict download URL binding, and accept that channel in published metadata. A beta or release candidate still wins whenever the API offers one. --- .../docs-playground-preview/lib/config.mjs | 36 +++++--- .../lib/publication.mjs | 10 ++- .../test/config.test.mjs | 85 ++++++++++++++++++- .../test/publication.test.mjs | 44 ++++++++++ 4 files changed, 161 insertions(+), 14 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index 633ae0bf3f6fb..b101bad41c6f3 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -5,6 +5,7 @@ const FULL_COMMIT = /^[0-9a-f]{40}$/; const FULL_DIGEST = /^[0-9a-f]{64}$/; const VERSION = /^\d+\.\d+\.\d+$/; const API_BETA_VERSION = /^\d+\.\d+(?:\.\d+)?-(?:beta\d+|RC\d+)$/; +const API_STABLE_VERSION = /^\d+\.\d+(?:\.\d+)?$/; const OFFICIAL_REPOSITORIES = Object.freeze( { phpdocParser: 'WordPress/phpdoc-parser', wporgDeveloper: 'WordPress/wporg-developer', @@ -147,21 +148,34 @@ export async function resolveWordPressBeta( ); } const body = await response.json(); - const offer = body?.offers?.find( - ( candidate ) => - API_BETA_VERSION.test( candidate?.version ) && - candidate.download === - `https://downloads.wordpress.org/release/wordpress-${ candidate.version }.zip` - ); - if ( ! offer ) { + const findOfficialOffer = ( versionPattern ) => + body?.offers?.find( + ( candidate ) => + versionPattern.test( candidate?.version ) && + candidate.download === + `https://downloads.wordpress.org/release/wordpress-${ candidate.version }.zip` + ); + const betaOffer = findOfficialOffer( API_BETA_VERSION ); + if ( betaOffer ) { + return Object.freeze( { + channel: 'beta', + version: betaOffer.version, + downloadUrl: betaOffer.download, + } ); + } + const stableOffer = findOfficialOffer( API_STABLE_VERSION ); + if ( ! stableOffer ) { throw new Error( - 'The WordPress beta API returned no concrete beta build.' + 'The WordPress beta API returned no concrete beta or stable build.' ); } + process.stderr.write( + `::notice::The WordPress beta channel offers no beta or RC build; tracking the stable release ${ stableOffer.version } until the next beta appears.\n` + ); return Object.freeze( { - channel: 'beta', - version: offer.version, - downloadUrl: offer.download, + channel: 'stable', + version: stableOffer.version, + downloadUrl: stableOffer.download, } ); } diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs index 24e89063c7501..53f1f7792b76c 100644 --- a/.github/scripts/docs-playground-preview/lib/publication.mjs +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -200,10 +200,16 @@ export function validatePublishedSnapshotMetadata( metadata, expected ) { ) { throw new Error( 'Published snapshot identity is invalid.' ); } + const resolvedVersionPattern = + metadata.resolvedWordPressBeta?.channel === 'beta' + ? /^\d+\.\d+(?:\.\d+)?-(?:beta\d+|RC\d+)$/ + : metadata.resolvedWordPressBeta?.channel === 'stable' + ? /^\d+\.\d+(?:\.\d+)?$/ + : null; if ( metadata.phpVersion !== '8.4' || - metadata.resolvedWordPressBeta?.channel !== 'beta' || - ! /^\d+\.\d+(?:\.\d+)?-(?:beta\d+|RC\d+)$/.test( + ! resolvedVersionPattern || + ! resolvedVersionPattern.test( metadata.resolvedWordPressBeta.version || '' ) || metadata.resolvedWordPressBeta.downloadUrl !== diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 3b43da2b2e364..1cbd1f7610f57 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -141,13 +141,96 @@ test( 'the beta resolver rejects an unbound download URL', async () => { version: '7.2-beta1', download: 'https://example.com/wordpress.zip', }, + { + response: 'upgrade', + version: '7.1.2', + download: 'https://example.com/wordpress-stable.zip', + }, ], } ), } ) ), - /no concrete beta build/ + /no concrete beta or stable build/ + ); +} ); + +test( 'the beta resolver falls back to the latest stable build with a notice', async ( t ) => { + const write = t.mock.method( process.stderr, 'write', () => true ); + const resolved = await resolveWordPressBeta( async () => ( { + ok: true, + json: async () => ( { + offers: [ + { + response: 'upgrade', + version: '7.1.2', + download: + 'https://downloads.wordpress.org/release/wordpress-7.1.2.zip', + }, + { + response: 'autoupdate', + version: '7.0.3', + download: + 'https://downloads.wordpress.org/release/wordpress-7.0.3.zip', + }, + ], + } ), + } ) ); + assert.deepEqual( resolved, { + channel: 'stable', + version: '7.1.2', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.1.2.zip', + } ); + assert.equal( write.mock.callCount(), 1 ); + assert.match( + write.mock.calls[ 0 ].arguments[ 0 ], + /^::notice::.*tracking the stable release 7\.1\.2 until the next beta appears\./ ); } ); +test( 'the beta resolver prefers a beta build over a stable build', async () => { + const resolved = await resolveWordPressBeta( async () => ( { + ok: true, + json: async () => ( { + offers: [ + { + response: 'upgrade', + version: '7.1.2', + download: + 'https://downloads.wordpress.org/release/wordpress-7.1.2.zip', + }, + { + response: 'development', + version: '7.2-RC2', + download: + 'https://downloads.wordpress.org/release/wordpress-7.2-RC2.zip', + }, + ], + } ), + } ) ); + assert.deepEqual( resolved, { + channel: 'beta', + version: '7.2-RC2', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-RC2.zip', + } ); +} ); + +test( 'the beta resolver rejects a response with no usable build', async () => { + for ( const body of [ + {}, + { offers: [] }, + { offers: [ { response: 'upgrade', version: 'trunk' } ] }, + ] ) { + await assert.rejects( + resolveWordPressBeta( async () => ( { + ok: true, + json: async () => body, + } ) ), + /no concrete beta or stable build/ + ); + } +} ); + test( 'the cache key changes with every material base input', () => { const inputs = { cacheSchemaVersion: 1, diff --git a/.github/scripts/docs-playground-preview/test/publication.test.mjs b/.github/scripts/docs-playground-preview/test/publication.test.mjs index 353f8e10f9bc8..0a03d7acea977 100644 --- a/.github/scripts/docs-playground-preview/test/publication.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publication.test.mjs @@ -165,6 +165,50 @@ test( 'reusable metadata must identify a passed same-PR snapshot', () => { ); } ); +test( 'runtime identity accepts the stable fallback channel', () => { + const metadata = published(); + const stable = { + ...metadata, + resolvedWordPressBeta: { + channel: 'stable', + version: '7.1.2', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.1.2.zip', + }, + }; + assert.equal( validateReusableMetadata( stable, identity ), stable ); + assert.throws( + () => + validateReusableMetadata( + { + ...stable, + resolvedWordPressBeta: { + ...stable.resolvedWordPressBeta, + channel: 'nightly', + }, + }, + identity + ), + /runtime identity/ + ); + assert.throws( + () => + validateReusableMetadata( + { + ...stable, + resolvedWordPressBeta: { + channel: 'stable', + version: '7.2-beta1', + downloadUrl: + 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', + }, + }, + identity + ), + /runtime identity/ + ); +} ); + test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () => { const bytes = Buffer.from( 'snapshot' ); const metadata = published( bytes ); From 32a930a9ac7637ea27abb69087da535a5d1d2a3a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 12:56:38 +0400 Subject: [PATCH 45/59] Build/Test Tools: Replace orphaned preview assets Release asset names are derived from the run and attempt, so a partial publication that also fails to clean up leaves a name that can never be uploaded again. Every re-run of that attempt fails with HTTP 422, reports the build as broken, and consumes the request label until someone deletes the asset by hand. Confirm the duplicate by listing the release, delete the stale asset, and retry the upload once. Report the HTTP status on API errors so callers can branch on it. --- .../docs-playground-preview/lib/github.mjs | 45 +++++++--- .../test/github.test.mjs | 85 +++++++++++++++++++ 2 files changed, 116 insertions(+), 14 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index f4078a40fb1eb..a95b82ad6ba81 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -45,11 +45,13 @@ export class GitHubApi { } if ( ! response.ok ) { const detail = await response.text(); - throw new Error( + const error = new Error( `GitHub API returned HTTP ${ response.status } for ${ url }: ${ detail.slice( 0, 300 ) }` ); + error.status = response.status; + throw error; } if ( response.status === 204 ) { return null; @@ -217,20 +219,35 @@ export class GitHubApi { ); } - uploadReleaseAsset( releaseId, name, bytes, contentType ) { - return this.request( - `${ UPLOADS }/repos/${ - this.repository - }/releases/${ releaseId }/assets?${ query( { name } ) }`, - { - method: 'POST', - headers: { - Accept: 'application/vnd.github+json', - 'Content-Type': contentType, - }, - body: bytes, + async uploadReleaseAsset( releaseId, name, bytes, contentType ) { + const upload = () => + this.request( + `${ UPLOADS }/repos/${ + this.repository + }/releases/${ releaseId }/assets?${ query( { name } ) }`, + { + method: 'POST', + headers: { + Accept: 'application/vnd.github+json', + 'Content-Type': contentType, + }, + body: bytes, + } + ); + try { + return await upload(); + } catch ( error ) { + if ( error.status !== 422 ) { + throw error; } - ); + const assets = await this.listReleaseAssets( releaseId ); + const stale = assets.find( ( asset ) => asset.name === name ); + if ( ! stale ) { + throw error; + } + await this.deleteReleaseAsset( stale.id ); + return upload(); + } } getGitReference( reference ) { diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index 0c445548cb38e..a94a666b91073 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -244,6 +244,91 @@ test( 'release operations keep immutable names and bytes', async () => { assert.equal( calls[ 4 ].options.method, 'DELETE' ); } ); +test( 'a stale duplicate asset is replaced and the upload retried once', async () => { + const calls = []; + let uploads = 0; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + calls.push( { url, options } ); + if ( url.startsWith( 'https://uploads.github.com' ) ) { + uploads++; + return uploads === 1 + ? response( { message: 'already_exists' }, 422 ) + : response( { id: 12, name: 'snapshot.zip' } ); + } + if ( options.method === 'DELETE' ) { + return response( null, 204 ); + } + return response( [ { id: 9, name: 'snapshot.zip' } ] ); + } + ); + const asset = await api.uploadReleaseAsset( + 5, + 'snapshot.zip', + Buffer.from( 'snapshot' ), + 'application/zip' + ); + assert.equal( asset.id, 12 ); + assert.equal( uploads, 2 ); + assert.match( calls[ 1 ].url, /releases\/5\/assets\?per_page/ ); + assert.match( calls[ 2 ].url, /releases\/assets\/9$/ ); + assert.equal( calls[ 2 ].options.method, 'DELETE' ); + assert.equal( calls[ 3 ].options.body.toString(), 'snapshot' ); +} ); + +test( 'a duplicate asset failure after the retry surfaces as an error', async () => { + let uploads = 0; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + if ( url.startsWith( 'https://uploads.github.com' ) ) { + uploads++; + return response( { message: 'already_exists' }, 422 ); + } + if ( options.method === 'DELETE' ) { + return response( null, 204 ); + } + return response( [ { id: 9, name: 'snapshot.zip' } ] ); + } + ); + await assert.rejects( + api.uploadReleaseAsset( + 5, + 'snapshot.zip', + Buffer.from( 'snapshot' ), + 'application/zip' + ), + /HTTP 422/ + ); + assert.equal( uploads, 2 ); + + let unrelatedUploads = 0; + const unrelated = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + if ( url.startsWith( 'https://uploads.github.com' ) ) { + unrelatedUploads++; + return response( { message: 'Validation Failed' }, 422 ); + } + return response( [] ); + } + ); + await assert.rejects( + unrelated.uploadReleaseAsset( + 5, + 'snapshot.zip', + Buffer.from( 'snapshot' ), + 'application/zip' + ), + /HTTP 422/ + ); + assert.equal( unrelatedUploads, 1 ); +} ); + test( 'Git object operations create and atomically move a pointer ref', async () => { const calls = []; const api = new GitHubApi( From 50252c05d9da18bd5c82a4e20658335346b5b243 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 12:56:38 +0400 Subject: [PATCH 46/59] Build/Test Tools: Verify the Composer download The base image downloads composer.phar over the network and executes it without any integrity check, and reuses the cached copy unverified. It is the only unpinned executable in an otherwise digest-pinned pipeline, so a compromised download would run inside the trusted trunk build that produces the published Blueprint. Pin the expected SHA-256 for the manifest's Composer version and verify both the downloaded and cached phar before use. A version without a recorded digest now fails closed. --- .../docs-playground-preview/lib/base.mjs | 35 +++++- .../test/base.test.mjs | 102 ++++++++++++++++++ 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/base.mjs b/.github/scripts/docs-playground-preview/lib/base.mjs index b21ee0f7f517f..81eef00bee3f4 100644 --- a/.github/scripts/docs-playground-preview/lib/base.mjs +++ b/.github/scripts/docs-playground-preview/lib/base.mjs @@ -3,7 +3,7 @@ import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { copyDirectory, downloadFile, zipDirectory } from './archive.mjs'; -import { acquireRepositories, exists } from './files.mjs'; +import { acquireRepositories, exists, sha256File } from './files.mjs'; import { buildSnapshot } from './playground.mjs'; import { run } from './process.mjs'; @@ -15,6 +15,13 @@ const TOOLING_ROOT = path.resolve( ); const PHP_ROOT = path.join( SCRIPT_ROOT, 'php' ); +// Official sha256 digests for getcomposer.org composer.phar releases, keyed +// by the toolchain.composerVersion pinned in the dependency manifest. +const COMPOSER_DIGESTS = Object.freeze( { + '2.8.12': + 'f446ea719708bb85fcbf4ef18def5d0515f1f9b4d703f6d820c9c1656e10a2f2', +} ); + function executable( name ) { return path.join( TOOLING_ROOT, @@ -193,15 +200,39 @@ export async function prunePreviewFonts( muPlugins ) { ); } -async function ensureComposer( inputs, tools, runImplementation ) { +export async function ensureComposer( + inputs, + tools, + runImplementation, + digests = COMPOSER_DIGESTS +) { const version = inputs.dependencies.toolchain.composerVersion; + const digest = digests[ version ]; + if ( ! digest ) { + throw new Error( + `Composer ${ version } has no pinned SHA-256 digest.` + ); + } const composer = path.join( tools, `composer-${ version }.phar` ); + if ( + ( await exists( composer ) ) && + ( await sha256File( composer ) ) !== digest + ) { + await rm( composer, { force: true } ); + } if ( ! ( await exists( composer ) ) ) { await downloadFile( `https://getcomposer.org/download/${ version }/composer.phar`, composer, runImplementation ); + const received = await sha256File( composer ); + if ( received !== digest ) { + await rm( composer, { force: true } ); + throw new Error( + `Composer ${ version } digest mismatch: expected ${ digest }, received ${ received }.` + ); + } } return composer; } diff --git a/.github/scripts/docs-playground-preview/test/base.test.mjs b/.github/scripts/docs-playground-preview/test/base.test.mjs index 690e3a6bbe190..2df4dbcbc1132 100644 --- a/.github/scripts/docs-playground-preview/test/base.test.mjs +++ b/.github/scripts/docs-playground-preview/test/base.test.mjs @@ -1,4 +1,5 @@ import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; import { mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; @@ -7,6 +8,7 @@ import { test } from 'node:test'; import { createInvariantBaseBlueprint, dependencyBuildPlan, + ensureComposer, ensureInvariantBase, prunePreviewFonts, } from '../lib/base.mjs'; @@ -28,6 +30,9 @@ function inputs( cacheDirectory ) { 'https://downloads.wordpress.org/release/wordpress-7.2-beta1.zip', }, dependencies: { + toolchain: { + composerVersion: '2.8.12', + }, playground: { blueprintSchema: 'https://playground.wordpress.net/blueprint-schema.json', @@ -37,6 +42,17 @@ function inputs( cacheDirectory ) { }; } +function sha256( bytes ) { + return createHash( 'sha256' ).update( bytes ).digest( 'hex' ); +} + +function fakeComposerDownload( bytes, downloads ) { + return async ( command, args ) => { + downloads.count++; + await writeFile( args[ args.indexOf( '--output' ) + 1 ], bytes ); + }; +} + test( 'the invariant Blueprint installs dependencies without importing source', () => { const blueprint = createInvariantBaseBlueprint( inputs( '/cache' ) ); assert.deepEqual( blueprint.preferredVersions, { @@ -87,6 +103,92 @@ test( 'dependency build plan uses pinned harness tools and upstream locks', () = ] ); } ); +test( 'a Composer download with the pinned digest is kept and reused', async () => { + const tools = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-composer-' ) + ); + const phar = 'good composer phar'; + const downloads = { count: 0 }; + const runImplementation = fakeComposerDownload( phar, downloads ); + const digests = { '2.8.12': sha256( phar ) }; + const cold = await ensureComposer( + inputs( '/cache' ), + tools, + runImplementation, + digests + ); + assert.equal( cold, path.join( tools, 'composer-2.8.12.phar' ) ); + assert.equal( await readFile( cold, 'utf8' ), phar ); + assert.equal( downloads.count, 1 ); + + const warm = await ensureComposer( + inputs( '/cache' ), + tools, + runImplementation, + digests + ); + assert.equal( warm, cold ); + assert.equal( downloads.count, 1 ); +} ); + +test( 'a Composer download failing digest verification is removed', async () => { + const tools = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-composer-' ) + ); + const downloads = { count: 0 }; + await assert.rejects( + ensureComposer( + inputs( '/cache' ), + tools, + fakeComposerDownload( 'tampered phar', downloads ), + { '2.8.12': sha256( 'good composer phar' ) } + ), + /digest mismatch/ + ); + assert.equal( downloads.count, 1 ); + await assert.rejects( + readFile( path.join( tools, 'composer-2.8.12.phar' ) ) + ); +} ); + +test( 'a cached Composer phar failing digest verification is replaced', async () => { + const tools = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-composer-' ) + ); + const phar = 'good composer phar'; + const downloads = { count: 0 }; + await writeFile( + path.join( tools, 'composer-2.8.12.phar' ), + 'tampered phar' + ); + const composer = await ensureComposer( + inputs( '/cache' ), + tools, + fakeComposerDownload( phar, downloads ), + { '2.8.12': sha256( phar ) } + ); + assert.equal( await readFile( composer, 'utf8' ), phar ); + assert.equal( downloads.count, 1 ); +} ); + +test( 'Composer versions without a pinned digest are rejected', async () => { + const tools = await mkdtemp( + path.join( os.tmpdir(), 'docs-preview-composer-' ) + ); + const resolved = inputs( '/cache' ); + resolved.dependencies.toolchain.composerVersion = '9.9.9'; + const downloads = { count: 0 }; + await assert.rejects( + ensureComposer( + resolved, + tools, + fakeComposerDownload( 'unused', downloads ) + ), + /no pinned SHA-256 digest/ + ); + assert.equal( downloads.count, 0 ); +} ); + test( 'the invariant base marker is written last and enables exact reuse', async () => { const cache = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-base-' ) From 866f4639b552b372577a1d5529c4f43a524195be Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 12:56:48 +0400 Subject: [PATCH 47/59] Build/Test Tools: Yield gracefully in lifecycle races Only the first authorization in the stale pass caught supersession, so re-adding the label during the slow snapshot download turned the trusted lifecycle job red. Expiry folded per-item supersession into an AggregateError, so reopening a pull request mid-cleanup failed the job with the preview half deleted. Route every supersession through the same graceful result in both paths, and stop expiry at the first superseded item so the comment is never marked expired while assets remain. Genuine failures still fail the job. --- .../docs-playground-preview/lifecycle.mjs | 38 ++++++++--- .../test/lifecycle.test.mjs | 64 ++++++++++++++++++- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index 1daf868ac6e6a..29979d8342ce1 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -139,13 +139,17 @@ async function authorizeStaleMutation( session, expectedComment ) { async function markStale( session ) { try { - await session.authorize( 'open', true ); + return await markStaleAuthorized( session ); } catch ( error ) { if ( error instanceof LifecycleSuperseded ) { return { status: 'ignored' }; } throw error; } +} + +async function markStaleAuthorized( session ) { + await session.authorize( 'open', true ); const comment = await session.api.findPreviewComment( session.context.pullRequestNumber ); @@ -201,10 +205,13 @@ async function settle( operations ) { try { await operation(); } catch ( error ) { + if ( error instanceof LifecycleSuperseded ) { + return { errors, superseded: true }; + } errors.push( error ); } } - return errors; + return { errors, superseded: false }; } async function expire( session ) { @@ -231,21 +238,25 @@ async function expire( session ) { const comment = await session.api.findPreviewComment( session.context.pullRequestNumber ); - const assetErrors = await settle( + const assetCleanup = await settle( assets.map( ( asset ) => async () => { await session.authorize( 'closed' ); await session.api.deleteReleaseAsset( asset.id ); } ) ); - const cacheErrors = await settle( + const cacheCleanup = await settle( caches.map( ( cache ) => async () => { await session.authorize( 'closed' ); await session.api.deleteActionCache( cache.id ); } ) ); - let commentErrors = []; - if ( comment && assetErrors.length === 0 ) { - commentErrors = await settle( [ + let commentCleanup = { errors: [], superseded: false }; + if ( + comment && + assetCleanup.errors.length === 0 && + ! assetCleanup.superseded + ) { + commentCleanup = await settle( [ async () => { await session.authorize( 'closed' ); await session.api.updateComment( @@ -255,10 +266,21 @@ async function expire( session ) { }, ] ); } - const errors = [ ...assetErrors, ...cacheErrors, ...commentErrors ]; + const errors = [ + ...assetCleanup.errors, + ...cacheCleanup.errors, + ...commentCleanup.errors, + ]; if ( errors.length > 0 ) { throw new AggregateError( errors, 'Pull request cleanup failed.' ); } + if ( + assetCleanup.superseded || + cacheCleanup.superseded || + commentCleanup.superseded + ) { + return { status: 'superseded' }; + } return { status: 'expired', deletedAssets: assets.length, diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index ac5c63dc9f2ed..624e43e7d12b3 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -106,9 +106,16 @@ class FakeApi { this.cacheRef = null; this.replacementComment = null; this.commentReads = 0; + this.laterPullRequest = null; + this.pullRequestReads = 0; + this.reopenAfterAssetDeletion = false; } async getPullRequest() { + this.pullRequestReads++; + if ( this.pullRequestReads > 1 && this.laterPullRequest ) { + return this.laterPullRequest; + } return this.currentPullRequest; } @@ -144,6 +151,9 @@ class FakeApi { throw new Error( 'release deletion failed' ); } this.deletedAssets.push( id ); + if ( this.reopenAfterAssetDeletion ) { + this.currentPullRequest = pullRequest( 'open' ); + } } async deleteActionCache( id ) { @@ -258,10 +268,21 @@ test( 'a newer terminal comment supersedes an older stale event', async () => { previous: previewMetadata(), } ), }; - await assert.rejects( - managePullRequest( options( api, event( 'synchronize' ) ) ), - /superseded/ + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) + ); + assert.equal( result.status, 'ignored' ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 're-adding the label during a slow stale pass yields to the publisher', async () => { + const api = new FakeApi(); + installPreview( api ); + api.laterPullRequest = pullRequest( 'open', [ { name: 'docs-preview' } ] ); + const result = await managePullRequest( + options( api, event( 'synchronize' ) ) ); + assert.equal( result.status, 'ignored' ); assert.equal( api.commentBodies.length, 0 ); } ); @@ -369,6 +390,43 @@ test( 'asset cleanup failure preserves a comment that still links live assets', assert.equal( api.commentBodies.length, 0 ); } ); +test( 'a reopen during asset deletion stops cleanup without failing the job', async () => { + const api = new FakeApi(); + api.currentPullRequest = pullRequest( 'closed' ); + installPreview( api ); + api.reopenAfterAssetDeletion = true; + api.caches.push( { + id: 10, + ref: 'refs/pull/123/merge', + key: `docs-preview-base-v1-${ 'd'.repeat( 64 ) }`, + } ); + const result = await managePullRequest( options( api, event( 'closed' ) ) ); + assert.equal( result.status, 'superseded' ); + assert.deepEqual( api.deletedAssets, [ 1 ] ); + assert.deepEqual( api.deletedCaches, [] ); + assert.equal( api.commentBodies.length, 0 ); +} ); + +test( 'a reopen mid-cleanup still surfaces genuine deletion failures', async () => { + const api = new FakeApi(); + api.currentPullRequest = pullRequest( 'closed' ); + installPreview( api ); + api.failedAsset = 1; + api.reopenAfterAssetDeletion = true; + api.caches.push( { + id: 10, + ref: 'refs/pull/123/merge', + key: `docs-preview-base-v1-${ 'd'.repeat( 64 ) }`, + } ); + await assert.rejects( + managePullRequest( options( api, event( 'closed' ) ) ), + /Pull request cleanup failed/ + ); + assert.deepEqual( api.deletedAssets, [ 2 ] ); + assert.deepEqual( api.deletedCaches, [] ); + assert.equal( api.commentBodies.length, 0 ); +} ); + test( 'a reopened PR supersedes close cleanup before any deletion', async () => { const api = new FakeApi(); installPreview( api ); From 4462b8a4fc31899aa3b5e1ad8e03159fe6c3daf9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 13:01:30 +0400 Subject: [PATCH 48/59] Build/Test Tools: Yield gracefully in publisher startup races Both publishers validate the triggering run before the session exists, outside the wrapper that turns supersession into a graceful result. A build re-run, a still-running attempt, or a fork deleted between build and publication therefore fails the trusted job red, even though the identical checks inside the session report the run as superseded. Mark the routine races distinctly from identity failures and report them as superseded from the establishment path as well. Genuine API outages and invalid run identities still fail the job. --- .../docs-playground-preview/lib/trunk.mjs | 18 +++++-- .../docs-playground-preview/publish-trunk.mjs | 15 +++++- .../docs-playground-preview/publish.mjs | 27 ++++++++-- .../test/publish-trunk.test.mjs | 41 +++++++++++++++ .../test/publish.test.mjs | 50 +++++++++++++++++++ .../test/trunk.test.mjs | 40 +++++++++++++++ 6 files changed, 183 insertions(+), 8 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs index 86638cd5cc82d..617fd9d90815e 100644 --- a/.github/scripts/docs-playground-preview/lib/trunk.mjs +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -40,6 +40,12 @@ function timestamp( value, label ) { return value; } +function supersededTrunkError( message ) { + const error = new Error( message ); + error.trunkRunSuperseded = true; + return error; +} + export function trunkSnapshotAssetName( identity ) { if ( ! FULL_COMMIT.test( identity.sourceSha || '' ) ) { throw new Error( 'sourceSha must be a full lowercase commit hash.' ); @@ -87,18 +93,22 @@ export function validateTrunkPublicationContext( context ) { runAttempt !== positiveInteger( context.triggerRunAttempt, 'Trigger run attempt' ) ) { - throw new Error( + throw supersededTrunkError( 'The triggering workflow attempt is no longer current.' ); } if ( context.run.name !== TRUNK_BUILD_WORKFLOW_NAME || context.run.event !== 'push' || - context.run.status !== 'completed' || context.run.head_branch !== 'trunk' ) { throw new Error( 'The trunk source workflow identity is invalid.' ); } + if ( context.run.status !== 'completed' ) { + throw supersededTrunkError( + 'The trunk source workflow is not terminal.' + ); + } const sourceSha = context.run.head_sha; if ( ! FULL_COMMIT.test( sourceSha || '' ) || @@ -123,7 +133,9 @@ export function assertLatestTrunkAuthorized( context ) { context.latestRun?.run_attempt !== current.workflowRunAttempt || context.trunkHeadSha !== current.sourceSha ) { - throw new Error( 'A newer trunk build superseded this attempt.' ); + throw supersededTrunkError( + 'A newer trunk build superseded this attempt.' + ); } return current; } diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index e7c942c5bc2df..9f191c8407715 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -292,7 +292,15 @@ async function publishCandidate( session, metadata, uploaded, transaction ) { } export async function publishTrunk( options ) { - const session = await establishSession( options ); + let session; + try { + session = await establishSession( options ); + } catch ( error ) { + if ( error.trunkRunSuperseded === true ) { + return { status: 'superseded' }; + } + throw error; + } const uploaded = []; const transaction = { pointerPublished: false }; try { @@ -320,7 +328,10 @@ export async function publishTrunk( options ) { if ( ! transaction.pointerPublished && ! error.pointerStateUnknown ) { await cleanupUploaded( session, uploaded ); } - if ( error instanceof SupersededTrunkRun ) { + if ( + error instanceof SupersededTrunkRun || + error.trunkRunSuperseded === true + ) { return { status: 'superseded' }; } throw error; diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 3a7cfd92496fe..738b7dc55a3b8 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -48,7 +48,15 @@ async function establishSession( options ) { options.fetchImplementation ); const run = await api.getRun( options.triggerRunId ); - const pullRequest = await api.findPullRequestForRun( run ); + let pullRequest; + try { + pullRequest = await api.findPullRequestForRun( run ); + } catch ( error ) { + if ( run.head_repository?.owner?.login && run.head_branch ) { + throw error; + } + throw new SupersededRun( error.message ); + } if ( ! pullRequest ) { return null; } @@ -60,7 +68,12 @@ async function establishSession( options ) { run, pullRequest, }; - const context = validatePublicationContext( base ); + let context; + try { + context = validatePublicationContext( base ); + } catch ( error ) { + throw new SupersededRun( error.message ); + } return { api, context, @@ -319,7 +332,15 @@ async function reuseCandidate( session, metadata ) { } export async function publishPullRequest( options ) { - const session = await establishSession( options ); + let session; + try { + session = await establishSession( options ); + } catch ( error ) { + if ( error instanceof SupersededRun ) { + return { status: 'superseded' }; + } + throw error; + } if ( ! session ) { return { status: 'superseded' }; } diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index 9ebd9c089a33b..18dcbc1a7cbdd 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -543,3 +543,44 @@ test( 'invalid, missing, and superseded handoffs never move the pointer', async ); assert.equal( supersededApi.assets.length, 3 ); } ); + +test( 'routine supersession races resolve green before the session starts', async () => { + const rerunApi = new FakeApi(); + installPrevious( rerunApi ); + rerunApi.currentRun = run( { run_attempt: 2 } ); + assert.equal( + ( + await publishTrunk( + options( rerunApi, await handoffDirectory( buildMetadata() ) ) + ) + ).status, + 'superseded' + ); + assert.equal( rerunApi.assets.length, 3 ); + + const activeApi = new FakeApi(); + installPrevious( activeApi ); + activeApi.currentRun = run( { status: 'in_progress' } ); + assert.equal( + ( + await publishTrunk( + options( activeApi, await handoffDirectory( buildMetadata() ) ) + ) + ).status, + 'superseded' + ); + assert.equal( activeApi.assets.length, 3 ); +} ); + +test( 'a genuine source identity failure still fails red', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.currentRun = run( { head_branch: 'not-trunk' } ); + await assert.rejects( + publishTrunk( + options( api, await handoffDirectory( buildMetadata() ) ) + ), + /source workflow identity/ + ); + assert.equal( api.assets.length, 3 ); +} ); diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index 123ed316d3fa2..b4e9a47da754f 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -366,6 +366,56 @@ test( 'a superseded run makes no mutation', async () => { assert.equal( api.labelRemovals, 0 ); } ); +test( 'a re-run source workflow supersedes instead of failing', async () => { + const api = new FakeApi(); + api.currentRun = { ...run(), run_attempt: 2 }; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'superseded' ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); + assert.equal( api.labelRemovals, 0 ); +} ); + +test( 'an in-progress source workflow supersedes instead of failing', async () => { + const api = new FakeApi(); + api.currentRun = { ...run(), status: 'in_progress' }; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'superseded' ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); + assert.equal( api.labelRemovals, 0 ); +} ); + +test( 'a fork deleted before publication supersedes instead of failing', async () => { + const api = new FakeApi(); + api.currentRun = { ...run(), head_repository: null }; + api.findPullRequestForRun = async () => { + throw new Error( 'Workflow run has no fork head identity.' ); + }; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'superseded' ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); + assert.equal( api.labelRemovals, 0 ); +} ); + +test( 'pull request lookup outages remain visible failures', async () => { + const api = new FakeApi(); + api.findPullRequestForRun = async () => { + throw new Error( 'GitHub is unavailable' ); + }; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishPullRequest( options( api, directory ) ), + /GitHub is unavailable/ + ); + assert.equal( api.uploads.length, 0 ); + assert.equal( api.comments.length, 0 ); +} ); + test( 'a skipped trigger run makes no mutation', async () => { const api = new FakeApi(); api.isSkippedPreviewBuild = async () => true; diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs index b4ca1ad9f27bb..cd2468808a8ec 100644 --- a/.github/scripts/docs-playground-preview/test/trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -163,6 +163,46 @@ test( 'trunk publication binds the exact terminal push and latest head', () => { ); } ); +test( 'supersession races are marked distinctly from identity failures', () => { + assert.throws( + () => + validateTrunkPublicationContext( + context( { triggerRunAttempt: 1 } ) + ), + ( error ) => + error.trunkRunSuperseded === true && + /no longer current/.test( error.message ) + ); + assert.throws( + () => + validateTrunkPublicationContext( { + ...context(), + run: { ...context().run, status: 'in_progress' }, + } ), + ( error ) => + error.trunkRunSuperseded === true && + /not terminal/.test( error.message ) + ); + assert.throws( + () => + validateTrunkPublicationContext( { + ...context(), + run: { ...context().run, head_branch: 'main' }, + } ), + ( error ) => + error.trunkRunSuperseded === undefined && + /workflow identity/.test( error.message ) + ); + assert.throws( + () => + assertLatestTrunkAuthorized( { + ...context(), + latestRun: { ...context().run, id: 999 }, + } ), + ( error ) => error.trunkRunSuperseded === true + ); +} ); + test( 'the trunk handoff accepts only a passed exact-run candidate', () => { assert.equal( inspectTrunkHandoff( metadata(), context() ).kind, From 8bbee81ee91d673cd304e3c5337321eb8d0fcf6e Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 13:01:40 +0400 Subject: [PATCH 49/59] Build/Test Tools: Recreate a deleted preview comment Updating the preview comment has no fallback when the comment is gone. Deleting it while a publication runs turns the update into an HTTP 404 that reaches the transaction handler, which deletes the freshly validated snapshot, reports the successful build as failed, and removes the request label. Create a replacement comment when the update reports that it no longer exists. Every other update failure still fails the publication. --- .../docs-playground-preview/publish.mjs | 18 +++++--- .../test/publish.test.mjs | 43 +++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index 738b7dc55a3b8..c671bea3e9f75 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -127,13 +127,19 @@ async function upsertComment( session, body ) { ); await session.authorize(); if ( comment ) { - await session.api.updateComment( comment.id, body ); - } else { - await session.api.createComment( - session.context.pullRequestNumber, - body - ); + try { + await session.api.updateComment( comment.id, body ); + return; + } catch ( error ) { + if ( error.status !== 404 ) { + throw error; + } + session.warning( + `Cannot update the deleted preview comment: ${ error.message }` + ); + } } + await session.api.createComment( session.context.pullRequestNumber, body ); } async function removeRequestLabel( session ) { diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index b4e9a47da754f..9f89c96d79e39 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -574,6 +574,49 @@ test( 'a healthy same-SHA preview is reused without uploading it again', async ( assert.equal( api.labelRemovals, 1 ); } ); +test( 'a preview comment deleted mid-update is recreated', async () => { + const api = new FakeApi(); + api.comments = [ { id: 7, body: 'about to be deleted' } ]; + api.updateComment = async () => { + const error = new Error( + `GitHub API returned HTTP 404 for /repos/${ repository }/issues/comments/7: Not Found` + ); + error.status = 404; + throw error; + }; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishPullRequest( options( api, directory ) ); + assert.equal( result.status, 'ready' ); + assert.equal( api.comments[ 0 ].number, 123 ); + assert.match( api.comments[ 0 ].body, /Status:\*\* Ready/ ); + assert.deepEqual( api.deleted, [] ); + assert.equal( api.labelRemovals, 1 ); +} ); + +test( 'a non-404 comment update failure still fails the publication', async () => { + const api = new FakeApi(); + api.comments = [ { id: 7, body: 'existing preview comment' } ]; + api.updateComment = async () => { + throw new Error( + `GitHub API returned HTTP 500 for /repos/${ repository }/issues/comments/7: boom` + ); + }; + const directory = await handoffDirectory( buildMetadata() ); + await assert.rejects( + publishPullRequest( options( api, directory ) ), + ( error ) => { + assert.ok( error instanceof AggregateError ); + assert.match( error.errors[ 0 ].message, /HTTP 500/ ); + return true; + } + ); + assert.equal( api.comments[ 0 ].id, 7 ); + assert.deepEqual( + api.deleted.sort( ( left, right ) => left - right ), + [ 10, 11 ] + ); +} ); + test( 'cleanup failure cannot replace an already-ready comment', async () => { const api = new FakeApi(); api.assets.push( From 68dbda9aa5526a41ba0e117b2ce42e68dc3bb578 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 13:02:13 +0400 Subject: [PATCH 50/59] Build/Test Tools: Publish the newest built trunk snapshot Trunk publication also required the branch head to equal the built commit, so a push that produces no build run supersedes a finished one. A commit landing with [skip ci], or a run lost to an incident, therefore discards the completed snapshot with a green job, and no later run can ever satisfy the check, leaving the stable preview stale until an unrelated push happens to succeed. Supersede a publication only when a newer trunk build run exists, and record a notice when the branch head has moved past the commit being published. Every other authorization check is unchanged. --- .../docs-playground-preview/lib/trunk.mjs | 3 +-- .../docs-playground-preview/publish-trunk.mjs | 14 ++++++++++++- .../test/publish-trunk.test.mjs | 20 +++++++++++++++++++ .../test/trunk.test.mjs | 17 +++++++++++++++- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs index 617fd9d90815e..def0b455bf865 100644 --- a/.github/scripts/docs-playground-preview/lib/trunk.mjs +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -130,8 +130,7 @@ export function assertLatestTrunkAuthorized( context ) { const current = validateTrunkPublicationContext( context ); if ( context.latestRun?.id !== current.workflowRunId || - context.latestRun?.run_attempt !== current.workflowRunAttempt || - context.trunkHeadSha !== current.sourceSha + context.latestRun?.run_attempt !== current.workflowRunAttempt ) { throw supersededTrunkError( 'A newer trunk build superseded this attempt.' diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index 9f191c8407715..a504de1c9685f 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -51,6 +51,10 @@ async function establishSession( options ) { run, }; const context = validateTrunkPublicationContext( base ); + const notice = + options.notice || + ( ( message ) => process.stdout.write( `${ message }\n` ) ); + let staleHeadReported = false; return { api, context, @@ -65,8 +69,9 @@ async function establishSession( options ) { const currentRun = await api.getRun( options.triggerRunId ); const latestRun = await api.latestTrunkPreviewRun(); const trunkHeadSha = await api.getTrunkHeadSha(); + let current; try { - return assertLatestTrunkAuthorized( { + current = assertLatestTrunkAuthorized( { ...base, run: currentRun, latestRun, @@ -75,6 +80,13 @@ async function establishSession( options ) { } catch ( error ) { throw new SupersededTrunkRun( error.message ); } + if ( trunkHeadSha !== current.sourceSha && ! staleHeadReported ) { + staleHeadReported = true; + notice( + `::notice::Trunk head ${ trunkHeadSha } has no newer Code Reference build; publishing the completed build for ${ current.sourceSha }.` + ); + } + return current; }, }; } diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index 18dcbc1a7cbdd..f57f69c0ab280 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -292,6 +292,7 @@ function options( api, directory, extra = {} ) { fetchImplementation: publicFetch( api ), now: () => '2026-08-09T13:00:00.000Z', warning: () => {}, + notice: () => {}, ...extra, }; } @@ -584,3 +585,22 @@ test( 'a genuine source identity failure still fails red', async () => { ); assert.equal( api.assets.length, 3 ); } ); + +test( 'a trunk head without a newer build run still publishes with a notice', async () => { + const api = new FakeApi(); + installPrevious( api ); + api.trunkHeadSha = 'b'.repeat( 40 ); + const notices = []; + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishTrunk( + options( api, directory, { + notice: ( message ) => notices.push( message ), + } ) + ); + assert.equal( result.status, 'ready' ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.equal( notices.length, 1 ); + assert.match( notices[ 0 ], /^::notice::/ ); + assert.ok( notices[ 0 ].includes( 'b'.repeat( 40 ) ) ); + assert.ok( notices[ 0 ].includes( sha ) ); +} ); diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs index cd2468808a8ec..0ddafa20cc00e 100644 --- a/.github/scripts/docs-playground-preview/test/trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -153,11 +153,26 @@ test( 'trunk publication binds the exact terminal push and latest head', () => { } ), /source workflow identity/ ); + assert.equal( + assertLatestTrunkAuthorized( { + ...context(), + trunkHeadSha: 'c'.repeat( 40 ), + } ).sourceSha, + sha + ); + assert.throws( + () => + assertLatestTrunkAuthorized( { + ...context(), + latestRun: { ...context().run, id: 789 }, + } ), + /superseded/ + ); assert.throws( () => assertLatestTrunkAuthorized( { ...context(), - trunkHeadSha: 'c'.repeat( 40 ), + latestRun: { ...context().run, run_attempt: 3 }, } ), /superseded/ ); From d9e6d1c70594ccbca4d021d015af8afe4ab0de36 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 13:02:43 +0400 Subject: [PATCH 51/59] Build/Test Tools: Survive CDN caching of the trunk pointer The pointer transaction reads the stable Blueprint back over the raw CDN, which caches the branch path for minutes and can still serve the previous Blueprint. That fails a publication which actually succeeded and strands its assets. The same cache keeps handing out Blueprints that reference the snapshot the publication deletes as soon as the pointer moves, so the stable preview link breaks for several minutes after every trunk build. Read the moved pointer back through the contents API, which is never cached, and retain the previous snapshot generation for one more publication so cached Blueprints stay resolvable. --- .../docs-playground-preview/publish-trunk.mjs | 63 ++++++++++++--- .../test/publish-trunk.test.mjs | 78 +++++++++++++++---- 2 files changed, 117 insertions(+), 24 deletions(-) diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index a504de1c9685f..bfe98aadd1f16 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -20,7 +20,6 @@ import { createTrunkPublishedMetadata, inspectTrunkHandoff, trunkBlueprintCommitUrl, - trunkStableBlueprintUrl, validatePublicBlueprint, validatePublishedTrunkMetadata, validateTrunkPublicationContext, @@ -28,6 +27,10 @@ import { class SupersededTrunkRun extends Error {} +const TRUNK_POINTER_BRANCH = TRUNK_POINTER_REF.replace( /^heads\//, '' ); +const TRUNK_GENERATION_ASSET = + /^(code-reference-trunk-[0-9a-f]{40}-(\d+)-(\d+))\.(?:zip|json)$/; + async function readHandoff( directory ) { return JSON.parse( await readFile( path.join( directory, 'build.json' ), 'utf8' ) @@ -130,6 +133,31 @@ async function validatePublicMetadata( session, asset, expected ) { return metadata; } +async function validateStablePointerContent( session, expected ) { + // The raw CDN caches the branch-path Blueprint for minutes, so the + // post-move read-back must use the authoritative contents API instead. + const file = await session.api.request( + `/repos/${ session.repository }/contents/${ TRUNK_POINTER_ASSET }?ref=${ TRUNK_POINTER_BRANCH }` + ); + if ( file?.encoding !== 'base64' || typeof file.content !== 'string' ) { + throw new Error( 'The stable trunk pointer content is unreadable.' ); + } + let blueprint; + try { + blueprint = JSON.parse( + Buffer.from( file.content, 'base64' ).toString( 'utf8' ) + ); + } catch { + throw new Error( 'The stable trunk pointer content is not JSON.' ); + } + if ( ! isDeepStrictEqual( blueprint, expected ) ) { + throw new Error( + 'The stable trunk pointer does not identify the candidate.' + ); + } + return blueprint; +} + async function cleanupUploaded( session, uploaded ) { for ( const asset of uploaded ) { try { @@ -226,11 +254,30 @@ async function moveStablePointer( session, previousRef, commit, transaction ) { async function cleanupOldTrunkAssets( session, release, keepIds ) { const assets = await session.api.listReleaseAssets( release.id ); + const generations = new Map(); for ( const asset of assets ) { - if ( - asset.name.startsWith( 'code-reference-trunk-' ) && - ! keepIds.has( asset.id ) - ) { + const match = asset.name.match( TRUNK_GENERATION_ASSET ); + if ( ! match || keepIds.has( asset.id ) ) { + continue; + } + const generation = generations.get( match[ 1 ] ) || { + runId: Number( match[ 2 ] ), + runAttempt: Number( match[ 3 ] ), + assets: [], + }; + generation.assets.push( asset ); + generations.set( match[ 1 ], generation ); + } + // Warm raw CDN copies of the stable Blueprint may reference the previous + // snapshot for minutes, so it survives exactly one more publish cycle. + const disposable = [ ...generations.values() ] + .sort( + ( left, right ) => + right.runId - left.runId || right.runAttempt - left.runAttempt + ) + .slice( 1 ); + for ( const generation of disposable ) { + for ( const asset of generation.assets ) { await session.authorize(); await session.api.deleteReleaseAsset( asset.id ); } @@ -290,11 +337,7 @@ async function publishCandidate( session, metadata, uploaded, transaction ) { blueprint ); await moveStablePointer( session, previousRef, pointerCommit, transaction ); - await validatePublicBlueprint( - trunkStableBlueprintUrl( session.repository ), - blueprint, - session.fetchImplementation - ); + await validateStablePointerContent( session, blueprint ); await cleanupOldTrunkAssets( session, release, diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index f57f69c0ab280..63a70f0649660 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -92,6 +92,25 @@ class FakeApi { this.refUpdateFailure = null; this.failRefResolution = false; this.staleRefAfterMutation = false; + this.staleContents = false; + } + + async request( url ) { + assert.equal( + url, + `/repos/${ repository }/contents/code-reference-trunk.json?ref=docs-preview-code-reference` + ); + const contentSha = this.staleContents + ? this.previousRefSha + : this.refSha; + this.events.push( `contents:${ contentSha }` ); + const bytes = this.commits.get( contentSha ); + if ( ! bytes ) { + throw new Error( + 'GitHub API returned HTTP 404 for the pointer contents.' + ); + } + return { encoding: 'base64', content: bytes.toString( 'base64' ) }; } async getRun() { @@ -342,9 +361,20 @@ function installPrevious( api ) { return { build, published }; } +function installOlder( api ) { + const olderName = trunkSnapshotAssetName( { + sourceSha: '1'.repeat( 40 ), + workflowRunId: 200, + workflowRunAttempt: 1, + } ); + addAsset( api, 5, olderName, 'older snapshot' ); + addAsset( api, 6, metadataAssetName( olderName ), '{}' ); +} + test( 'the stable pointer moves only after every candidate is public', async () => { const api = new FakeApi(); installPrevious( api ); + installOlder( api ); const current = buildMetadata(); const directory = await handoffDirectory( current ); const result = await publishTrunk( options( api, directory ) ); @@ -354,7 +384,9 @@ test( 'the stable pointer moves only after every candidate is public', async () api.commits.get( api.refSha ).toString( 'utf8' ) ); assert.match( blueprint.meta.description, new RegExp( sha ) ); - assert.deepEqual( api.deleted.sort(), [ 1, 2 ] ); + assert.deepEqual( api.deleted.sort(), [ 5, 6 ] ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 2 ) ); assert.ok( api.assets.some( ( asset ) => asset.id === 4 ) ); const candidateFetch = api.events.lastIndexOf( 'fetch:candidate-pointer' ); const pointerMove = api.events.lastIndexOf( @@ -363,7 +395,9 @@ test( 'the stable pointer moves only after every candidate is public', async () const pointerRead = api.events.lastIndexOf( `git:read-ref:${ 'f'.repeat( 40 ) }` ); - const stableFetch = api.events.lastIndexOf( 'fetch:stable-pointer' ); + const contentsRead = api.events.lastIndexOf( + `contents:${ 'f'.repeat( 40 ) }` + ); const firstDelete = api.events.findIndex( ( event ) => event.startsWith( 'delete:' ) ); @@ -371,23 +405,36 @@ test( 'the stable pointer moves only after every candidate is public', async () candidateFetch > -1 && candidateFetch < pointerMove && pointerMove < pointerRead && - pointerRead < stableFetch && - stableFetch < firstDelete + pointerRead < contentsRead && + contentsRead < firstDelete + ); +} ); + +test( 'stale raw delivery cannot fail publication or drop a generation', async () => { + const api = new FakeApi(); + installPrevious( api ); + const directory = await handoffDirectory( buildMetadata() ); + const result = await publishTrunk( + options( api, directory, { + fetchImplementation: publicFetch( api, { + staleStablePointer: true, + } ), + } ) ); + assert.equal( result.status, 'ready' ); + assert.equal( api.refSha, 'f'.repeat( 40 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); + assert.ok( api.assets.some( ( asset ) => asset.id === 10 ) ); + assert.deepEqual( api.deleted, [] ); } ); -test( 'stale stable delivery retains both snapshot generations', async () => { +test( 'a stale authoritative read-back fails without deleting snapshots', async () => { const api = new FakeApi(); installPrevious( api ); + api.staleContents = true; const directory = await handoffDirectory( buildMetadata() ); await assert.rejects( - publishTrunk( - options( api, directory, { - fetchImplementation: publicFetch( api, { - staleStablePointer: true, - } ), - } ) - ), + publishTrunk( options( api, directory ) ), /does not identify the candidate/ ); assert.equal( api.refSha, 'f'.repeat( 40 ) ); @@ -433,6 +480,7 @@ test( 'a failed ref update retains the previous and candidate assets', async () test( 'an ambiguous ref response resolves the candidate and completes', async () => { const api = new FakeApi(); installPrevious( api ); + installOlder( api ); api.refUpdateFailure = 'after'; const directory = await handoffDirectory( buildMetadata() ); assert.equal( @@ -440,7 +488,8 @@ test( 'an ambiguous ref response resolves the candidate and completes', async () 'ready' ); assert.equal( api.refSha, 'f'.repeat( 40 ) ); - assert.deepEqual( api.deleted.sort(), [ 1, 2 ] ); + assert.deepEqual( api.deleted.sort(), [ 5, 6 ] ); + assert.ok( api.assets.some( ( asset ) => asset.id === 1 ) ); } ); test( 'unresolved ref state retains both valid generations', async () => { @@ -491,7 +540,8 @@ test( 'an update error and stale read retain both asset generations', async () = test( 'cleanup failure keeps the new validated pointer and both snapshots', async () => { const api = new FakeApi(); installPrevious( api ); - api.deleteErrorId = 1; + installOlder( api ); + api.deleteErrorId = 5; const directory = await handoffDirectory( buildMetadata() ); await assert.rejects( publishTrunk( options( api, directory ) ), From cd4796b850db37d0dfb8dadf54c578de7e338319 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 13:02:50 +0400 Subject: [PATCH 52/59] Build/Test Tools: Report failed trunk validation The trunk publisher returns an invalid handoff as a successful no-op and never reads the enforcement variable that the pull request publisher honors. A behavioral validation failure, including a transient Playground boot flake, therefore skips publication with every job green, no annotation, and no comment, leaving the stable trunk preview silently pinned to an older commit. Enforce or annotate the invalid result the way the pull request publisher does, and pass the enforcement variable to the trunk publish step. --- .../docs-playground-preview/publish-trunk.mjs | 41 +++++++++++++++---- .../test/publish-trunk.test.mjs | 41 ++++++++++++++++++- .../docs-playground-preview-publish.yml | 3 ++ 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index bfe98aadd1f16..574ca207f75bd 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -393,17 +393,40 @@ export async function publishTrunk( options ) { } } +export function enforceTrunkValidationResult( + result, + enforcementVariable, + annotate = ( message ) => process.stdout.write( `${ message }\n` ) +) { + if ( result.status !== 'invalid' ) { + return result; + } + if ( enforcementVariable === 'true' ) { + throw new Error( + 'Code Reference validation failed with DOCS_PREVIEW_ENFORCE enabled.' + ); + } + annotate( + '::warning::Code Reference trunk validation failed; the stable trunk preview still points at the previous build.' + ); + return result; +} + async function main() { const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); - const result = await publishTrunk( { - repository: process.env.GITHUB_REPOSITORY, - stagingVariable: process.env.DOCS_PREVIEW_STAGING, - triggerRunId: event.workflow_run.id, - triggerRunAttempt: event.workflow_run.run_attempt, - handoffDirectory: process.argv[ 2 ] || 'handoff', - artifactAvailable: process.env.HANDOFF_DOWNLOAD_RESULT === 'success', - token: process.env.GITHUB_TOKEN, - } ); + const result = enforceTrunkValidationResult( + await publishTrunk( { + repository: process.env.GITHUB_REPOSITORY, + stagingVariable: process.env.DOCS_PREVIEW_STAGING, + triggerRunId: event.workflow_run.id, + triggerRunAttempt: event.workflow_run.run_attempt, + handoffDirectory: process.argv[ 2 ] || 'handoff', + artifactAvailable: + process.env.HANDOFF_DOWNLOAD_RESULT === 'success', + token: process.env.GITHUB_TOKEN, + } ), + process.env.DOCS_PREVIEW_ENFORCE + ); process.stdout.write( `Code Reference trunk publisher: ${ result.status }.\n` ); diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index 63a70f0649660..8e6aa7d856d51 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -16,7 +16,10 @@ import { createTrunkPublishedMetadata, trunkSnapshotAssetName, } from '../lib/trunk.mjs'; -import { publishTrunk } from '../publish-trunk.mjs'; +import { + enforceTrunkValidationResult, + publishTrunk, +} from '../publish-trunk.mjs'; const repository = 'WordPress/wordpress-develop'; const sha = 'a'.repeat( 40 ); @@ -654,3 +657,39 @@ test( 'a trunk head without a newer build run still publishes with a notice', as assert.ok( notices[ 0 ].includes( 'b'.repeat( 40 ) ) ); assert.ok( notices[ 0 ].includes( sha ) ); } ); + +test( 'trunk validation failures enforce or annotate visibly', () => { + const messages = []; + const annotate = ( message ) => messages.push( message ); + assert.equal( + enforceTrunkValidationResult( { status: 'ready' }, '', annotate ) + .status, + 'ready' + ); + assert.equal( + enforceTrunkValidationResult( + { status: 'superseded' }, + 'true', + annotate + ).status, + 'superseded' + ); + assert.deepEqual( messages, [] ); + assert.throws( + () => + enforceTrunkValidationResult( + { status: 'invalid' }, + 'true', + annotate + ), + /DOCS_PREVIEW_ENFORCE/ + ); + assert.deepEqual( messages, [] ); + assert.equal( + enforceTrunkValidationResult( { status: 'invalid' }, '', annotate ) + .status, + 'invalid' + ); + assert.equal( messages.length, 1 ); + assert.match( messages[ 0 ], /^::warning::/ ); +} ); diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index 49c4029a2c9da..7096a4bf758e1 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -102,7 +102,10 @@ jobs: digest-mismatch: error - name: Validate and publish the trunk handoff + # Administrator: enable enforcement in Settings > Secrets and variables > + # Actions > Variables by creating or updating DOCS_PREVIEW_ENFORCE to true. env: + DOCS_PREVIEW_ENFORCE: ${{ vars.DOCS_PREVIEW_ENFORCE }} DOCS_PREVIEW_STAGING: ${{ vars.DOCS_PREVIEW_STAGING }} GITHUB_TOKEN: ${{ github.token }} HANDOFF_DOWNLOAD_RESULT: ${{ steps.download.outcome }} From 4db798de3290f6f706ad0d0292d51d08ebf5c636 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 14:44:24 +0400 Subject: [PATCH 53/59] Add strict type checking to docs preview --- .../docs-playground-preview/package-lock.json | 4 +- .github/docs-playground-preview/package.json | 6 +- .github/docs-playground-preview/tsconfig.json | 15 ++ .../scripts/docs-playground-preview/build.mjs | 63 +++++++- .../docs-playground-preview/lib/archive.mjs | 21 +++ .../docs-playground-preview/lib/base.mjs | 40 ++++- .../docs-playground-preview/lib/config.mjs | 44 +++++- .../docs-playground-preview/lib/files.mjs | 32 +++- .../docs-playground-preview/lib/final.mjs | 11 ++ .../docs-playground-preview/lib/github.mjs | 107 +++++++++++++- .../docs-playground-preview/lib/inputs.mjs | 20 +++ .../docs-playground-preview/lib/parser.mjs | 15 ++ .../lib/playground.mjs | 9 +- .../docs-playground-preview/lib/process.mjs | 5 + .../lib/publication.mjs | 51 +++++++ .../docs-playground-preview/lib/published.mjs | 36 ++++- .../docs-playground-preview/lib/publisher.mjs | 63 +++++++- .../docs-playground-preview/lib/runtime.mjs | 9 ++ .../docs-playground-preview/lib/trunk.mjs | 64 +++++++- .../docs-playground-preview/lib/validate.mjs | 86 ++++++++++- .../docs-playground-preview/lifecycle.mjs | 93 ++++++++++-- .../docs-playground-preview/publish-trunk.mjs | 138 +++++++++++++++--- .../docs-playground-preview/publish.mjs | 130 +++++++++++++++-- .../scripts/docs-playground-preview/reuse.mjs | 32 +++- .../test/base.test.mjs | 52 ++++--- .../test/build.test.mjs | 27 +++- .../test/config.test.mjs | 2 +- .../test/files.test.mjs | 24 ++- .../test/final.test.mjs | 20 ++- .../test/github.test.mjs | 12 +- .../test/lifecycle.test.mjs | 54 ++++++- .../test/parser.test.mjs | 14 +- .../test/publication.test.mjs | 11 +- .../test/publish-trunk.test.mjs | 92 ++++++++++-- .../test/publish.test.mjs | 61 +++++++- .../test/published.test.mjs | 29 ++-- .../test/publisher.test.mjs | 13 +- .../test/trunk.test.mjs | 59 +++++--- .../test/validate.test.mjs | 13 +- 39 files changed, 1393 insertions(+), 184 deletions(-) create mode 100644 .github/docs-playground-preview/tsconfig.json diff --git a/.github/docs-playground-preview/package-lock.json b/.github/docs-playground-preview/package-lock.json index 087ed80d5d889..a81fc5d6c0e33 100644 --- a/.github/docs-playground-preview/package-lock.json +++ b/.github/docs-playground-preview/package-lock.json @@ -14,6 +14,9 @@ "@wp-playground/cli": "3.1.48", "yarn": "1.22.22" }, + "devDependencies": { + "typescript": "^6.0.3" + }, "engines": { "node": "20.20.2" } @@ -22144,7 +22147,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/.github/docs-playground-preview/package.json b/.github/docs-playground-preview/package.json index 63bccaa4d95c8..65a5011164dfc 100644 --- a/.github/docs-playground-preview/package.json +++ b/.github/docs-playground-preview/package.json @@ -9,12 +9,16 @@ }, "scripts": { "build": "node ../scripts/docs-playground-preview/build.mjs", - "test": "node --test ../scripts/docs-playground-preview/test/*.test.mjs" + "test": "node --test ../scripts/docs-playground-preview/test/*.test.mjs", + "typecheck": "tsc --build tsconfig.json" }, "dependencies": { "@wordpress/i18n": "6.24.0", "@wordpress/scripts": "32.6.0", "@wp-playground/cli": "3.1.48", "yarn": "1.22.22" + }, + "devDependencies": { + "typescript": "^6.0.3" } } diff --git a/.github/docs-playground-preview/tsconfig.json b/.github/docs-playground-preview/tsconfig.json new file mode 100644 index 0000000000000..122a2ab366db9 --- /dev/null +++ b/.github/docs-playground-preview/tsconfig.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "module": "NodeNext", + "noEmit": true, + "strict": true, + "target": "ES2022", + "types": [ "node" ], + "incremental": false, + "composite": false + }, + "include": [ "../scripts/docs-playground-preview/**/*.mjs" ] +} diff --git a/.github/scripts/docs-playground-preview/build.mjs b/.github/scripts/docs-playground-preview/build.mjs index a28bc9df241ad..067cf6946f0a8 100644 --- a/.github/scripts/docs-playground-preview/build.mjs +++ b/.github/scripts/docs-playground-preview/build.mjs @@ -24,6 +24,11 @@ const TOOLING_ROOT = path.join( const FULL_COMMIT = /^[0-9a-f]{40}$/; const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; +/** + * @param {string[]} args + * @param {number} index + * @param {string} name + */ function argumentValue( args, index, name ) { const value = args[ index + 1 ]; if ( ! value || value.startsWith( '--' ) ) { @@ -32,7 +37,11 @@ function argumentValue( args, index, name ) { return value; } +/** + * @param {string[]} args + */ export function parseArguments( args, environment = process.env ) { + /** @type {Record} */ const values = {}; for ( let index = 0; index < args.length; index++ ) { const name = args[ index ]; @@ -45,7 +54,11 @@ export function parseArguments( args, environment = process.env ) { } const key = name .slice( 2 ) - .replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() ); + .replace( + /-([a-z])/g, + /** @param {string} _ @param {string} letter */ ( _, letter ) => + letter.toUpperCase() + ); if ( ! [ 'source', @@ -75,6 +88,10 @@ export function parseArguments( args, environment = process.env ) { }; } +/** + * @param {unknown} value + * @param {string} label + */ function positiveInteger( value, label, nullable = true ) { if ( ( value === undefined || value === null || value === '' ) && @@ -89,6 +106,9 @@ function positiveInteger( value, label, nullable = true ) { return number; } +/** + * @param {string} remote + */ function githubRepository( remote ) { const match = remote .trim() @@ -98,6 +118,10 @@ function githubRepository( remote ) { return match?.[ 1 ] || null; } +/** + * @param {string} source + * @param {(...args: any[]) => any} runImplementation + */ async function gitIdentity( source, runImplementation ) { const sha = await runImplementation( 'git', [ 'rev-parse', 'HEAD' ], { cwd: source, @@ -121,6 +145,11 @@ async function gitIdentity( source, runImplementation ) { }; } +/** + * @param {Record} raw + * @param {Record} implementations + * @returns {Promise>} + */ async function normalizeOptions( raw, implementations ) { const workspace = path.join( REPOSITORY_ROOT, @@ -174,6 +203,9 @@ async function normalizeOptions( raw, implementations ) { }; } +/** + * @param {Record} implementations + */ async function ensureNodeTools( implementations ) { const playgroundCli = path.join( TOOLING_ROOT, @@ -189,6 +221,10 @@ async function ensureNodeTools( implementations ) { return playgroundCli; } +/** + * @param {Record} inputs + * @param {Record} [options] + */ export async function verifyToolchain( inputs, options = {} ) { const runImplementation = options.runImplementation || run; const expected = inputs.dependencies.toolchain; @@ -228,6 +264,15 @@ export async function verifyToolchain( inputs, options = {} ) { } } +/** + * @param {Record} options + * @param {Record} inputs + * @param {Record} base + * @param {Record} parser + * @param {Record} snapshot + * @param {Record} validation + * @param {string} generationTimestamp + */ export function createBuildMetadata( options, inputs, @@ -266,6 +311,12 @@ export function createBuildMetadata( }; } +/** + * @param {Record} options + * @param {Record} inputs + * @param {unknown} error + * @param {string} generationTimestamp + */ export function createFailureMetadata( options, inputs, @@ -290,10 +341,14 @@ export function createFailureMetadata( validationStatus: 'not-run', validationFailures: [], generationTimestamp, - buildError: error.message, + buildError: error instanceof Error ? error.message : String( error ), }; } +/** + * @param {string} filename + * @param {unknown} value + */ async function writeJson( filename, value ) { await mkdir( path.dirname( filename ), { recursive: true } ); await writeFile( filename, `${ JSON.stringify( value, null, 2 ) }\n` ); @@ -311,6 +366,10 @@ const DEFAULT_IMPLEMENTATIONS = { verifyToolchain, }; +/** + * @param {Record} rawOptions + * @returns {Promise>} + */ export async function buildCodeReferencePreview( rawOptions, overrides = {} ) { const implementations = { ...DEFAULT_IMPLEMENTATIONS, ...overrides }; const options = await normalizeOptions( rawOptions, implementations ); diff --git a/.github/scripts/docs-playground-preview/lib/archive.mjs b/.github/scripts/docs-playground-preview/lib/archive.mjs index d67e60cd2e25f..c8002b7ffdc90 100644 --- a/.github/scripts/docs-playground-preview/lib/archive.mjs +++ b/.github/scripts/docs-playground-preview/lib/archive.mjs @@ -6,13 +6,25 @@ import { run } from './process.mjs'; const DEFAULT_EXCLUDES = [ '.git', '.github', 'node_modules', 'tests' ]; +/** + * @param {string} relative + * @param {string[]} excludes + */ function isExcluded( relative, excludes ) { return excludes.some( + /** + * @param {string} excluded + */ ( excluded ) => relative === excluded || relative.startsWith( `${ excluded }/` ) ); } +/** + * @param {string} source + * @param {string} destination + * @param {string[]} excludes + */ export async function copyDirectory( source, destination, excludes = [] ) { const root = path.resolve( source ); await mkdir( destination, { recursive: true } ); @@ -25,6 +37,11 @@ export async function copyDirectory( source, destination, excludes = [] ) { } ); } +/** + * @param {string} source + * @param {string} output + * @param {string} rootName + */ export async function zipDirectory( source, output, @@ -52,6 +69,10 @@ export async function zipDirectory( } } +/** + * @param {string} url + * @param {string} output + */ export async function downloadFile( url, output, runImplementation = run ) { await mkdir( path.dirname( output ), { recursive: true } ); await runImplementation( diff --git a/.github/scripts/docs-playground-preview/lib/base.mjs b/.github/scripts/docs-playground-preview/lib/base.mjs index 81eef00bee3f4..4156d258db1a4 100644 --- a/.github/scripts/docs-playground-preview/lib/base.mjs +++ b/.github/scripts/docs-playground-preview/lib/base.mjs @@ -22,6 +22,9 @@ const COMPOSER_DIGESTS = Object.freeze( { 'f446ea719708bb85fcbf4ef18def5d0515f1f9b4d703f6d820c9c1656e10a2f2', } ); +/** + * @param {string} name + */ function executable( name ) { return path.join( TOOLING_ROOT, @@ -30,6 +33,10 @@ function executable( name ) { ); } +/** + * @param {Record} roots + * @param {string} composer + */ export function dependencyBuildPlan( roots, composer ) { const nodePath = path.join( TOOLING_ROOT, 'node_modules' ); const wpScriptsEnvironment = { NODE_PATH: nodePath }; @@ -122,10 +129,17 @@ export function dependencyBuildPlan( roots, composer ) { ]; } +/** + * @param {string} resourcePath + */ function bundled( resourcePath ) { return { resource: 'bundled', path: resourcePath }; } +/** + * @param {Record} inputs + * @returns {Record} + */ export function createInvariantBaseBlueprint( inputs ) { return { $schema: inputs.dependencies.playground.blueprintSchema, @@ -184,6 +198,9 @@ export function createInvariantBaseBlueprint( inputs ) { }; } +/** + * @param {string} muPlugins + */ export async function prunePreviewFonts( muPlugins ) { await rm( path.join( muPlugins, 'global-fonts/NotoSerif' ), { recursive: true, @@ -200,6 +217,12 @@ export async function prunePreviewFonts( muPlugins ) { ); } +/** + * @param {Record} inputs + * @param {string} tools + * @param {(...args: any[]) => any} runImplementation + * @param {Record} [digests] + */ export async function ensureComposer( inputs, tools, @@ -237,9 +260,14 @@ export async function ensureComposer( return composer; } +/** + * @param {string} upstreams + * @param {Record} inputs + */ function repositoryRoots( upstreams, inputs ) { - const root = ( name ) => path.join( upstreams, name ); - const selected = ( name ) => + const root = /** @param {string} name */ ( name ) => + path.join( upstreams, name ); + const selected = /** @param {string} name */ ( name ) => path.join( root( name ), inputs.dependencies.repositories[ name ].path @@ -256,6 +284,10 @@ function repositoryRoots( upstreams, inputs ) { }; } +/** + * @param {Record} inputs + * @param {Record} options + */ async function buildInvariantBase( inputs, options ) { const runImplementation = options.runImplementation || run; const work = path.join( inputs.cacheDirectory, 'work' ); @@ -330,6 +362,10 @@ async function buildInvariantBase( inputs, options ) { await rm( work, { recursive: true, force: true } ); } +/** + * @param {Record} inputs + * @param {Record} [options] + */ export async function ensureInvariantBase( inputs, options = {} ) { const markerFile = path.join( inputs.cacheDirectory, 'base.json' ); if ( await exists( markerFile ) ) { diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index b101bad41c6f3..b0f903d4c138f 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -21,24 +21,43 @@ const DEPLOYMENT_REPOSITORIES = new Set( [ const VERSION_API = 'https://api.wordpress.org/core/version-check/1.7/?channel=beta'; +/** + * @param {unknown} value + * @param {string} label + */ function assertObject( value, label ) { if ( ! value || typeof value !== 'object' || Array.isArray( value ) ) { throw new Error( `${ label } must be an object.` ); } } +/** + * @param {unknown} value + * @param {string} label + */ function assertPositiveInteger( value, label ) { - if ( ! Number.isSafeInteger( value ) || value < 1 ) { + if ( + typeof value !== 'number' || + ! Number.isSafeInteger( value ) || + value < 1 + ) { throw new Error( `${ label } must be a positive integer.` ); } } +/** + * @param {unknown} value + * @param {string} label + */ function assertDigest( value, label ) { if ( typeof value !== 'string' || ! FULL_DIGEST.test( value ) ) { throw new Error( `${ label } must be a lowercase SHA-256 digest.` ); } } +/** + * @param {Record} dependencies + */ export function validateDependencies( dependencies ) { assertObject( dependencies, 'Dependency manifest' ); if ( dependencies.schemaVersion !== 1 ) { @@ -127,15 +146,23 @@ export function validateDependencies( dependencies ) { return dependencies; } +/** + * @param {string} filename + */ export async function loadDependencies( filename ) { const bytes = await readFile( filename ); - const dependencies = validateDependencies( JSON.parse( bytes ) ); + const dependencies = validateDependencies( + JSON.parse( bytes.toString( 'utf8' ) ) + ); return { dependencies, digest: createHash( 'sha256' ).update( bytes ).digest( 'hex' ), }; } +/** + * @param {(...args: any[]) => Promise} [fetchImplementation] + */ export async function resolveWordPressBeta( fetchImplementation = globalThis.fetch ) { @@ -148,8 +175,13 @@ export async function resolveWordPressBeta( ); } const body = await response.json(); - const findOfficialOffer = ( versionPattern ) => + const findOfficialOffer = /** @param {RegExp} versionPattern */ ( + versionPattern + ) => body?.offers?.find( + /** + * @param {Record} candidate + */ ( candidate ) => versionPattern.test( candidate?.version ) && candidate.download === @@ -179,6 +211,9 @@ export async function resolveWordPressBeta( } ); } +/** + * @param {Record} inputs + */ export function makeBaseCacheKey( inputs ) { assertObject( inputs, 'Cache inputs' ); assertPositiveInteger( @@ -207,6 +242,9 @@ export function makeBaseCacheKey( inputs ) { return `docs-preview-base-v${ inputs.cacheSchemaVersion }-${ identity }`; } +/** + * @param {string} repository + */ export function isDeploymentEnabled( repository, stagingValue = '' ) { return ( DEPLOYMENT_REPOSITORIES.has( repository ) && diff --git a/.github/scripts/docs-playground-preview/lib/files.mjs b/.github/scripts/docs-playground-preview/lib/files.mjs index 3028c045dd631..8c609dadada97 100644 --- a/.github/scripts/docs-playground-preview/lib/files.mjs +++ b/.github/scripts/docs-playground-preview/lib/files.mjs @@ -9,18 +9,28 @@ const EXCLUDED_SOURCE_DIRECTORIES = new Set( [ 'wp-content/themes', ] ); +/** + * @param {string} filename + */ export async function exists( filename ) { try { await stat( filename ); return true; } catch ( error ) { - if ( error.code === 'ENOENT' ) { + if ( + error instanceof Error && + 'code' in error && + error.code === 'ENOENT' + ) { return false; } throw error; } } +/** + * @param {string} candidate + */ export async function findWordPressSourceRoot( candidate ) { const root = path.resolve( candidate ); for ( const directory of [ root, path.join( root, 'src' ) ] ) { @@ -33,6 +43,10 @@ export async function findWordPressSourceRoot( candidate ) { throw new Error( `No WordPress source tree found beneath ${ root }.` ); } +/** + * @param {string} root + * @returns {Promise} + */ async function listFiles( root, relative = '' ) { const files = []; const entries = await readdir( path.join( root, relative ), { @@ -51,6 +65,10 @@ async function listFiles( root, relative = '' ) { return files; } +/** + * @param {string} root + * @param {(relative: string) => boolean} [include] + */ export async function digestTree( root, include = () => true ) { const hash = createHash( 'sha256' ); for ( const relative of await listFiles( root ) ) { @@ -65,12 +83,19 @@ export async function digestTree( root, include = () => true ) { return hash.digest( 'hex' ); } +/** + * @param {string} filename + */ export async function sha256File( filename ) { return createHash( 'sha256' ) .update( await readFile( filename ) ) .digest( 'hex' ); } +/** + * @param {string} candidate + * @param {string} destination + */ export async function stageCorePhp( candidate, destination ) { const source = await findWordPressSourceRoot( candidate ); await rm( destination, { recursive: true, force: true } ); @@ -99,12 +124,17 @@ export async function stageCorePhp( candidate, destination ) { return { source, destination, files: count }; } +/** + * @param {Record} repositories + * @param {string} destination + */ export async function acquireRepositories( repositories, destination, runImplementation = run ) { await mkdir( destination, { recursive: true } ); + /** @type {Record} */ const acquired = {}; for ( const [ name, dependency ] of Object.entries( repositories ) ) { const target = path.join( destination, name ); diff --git a/.github/scripts/docs-playground-preview/lib/final.mjs b/.github/scripts/docs-playground-preview/lib/final.mjs index a9816b8e5314c..be9474b4757b4 100644 --- a/.github/scripts/docs-playground-preview/lib/final.mjs +++ b/.github/scripts/docs-playground-preview/lib/final.mjs @@ -9,10 +9,17 @@ import { renderRuntimePlugin } from './runtime.mjs'; const LIBRARY_ROOT = path.dirname( fileURLToPath( import.meta.url ) ); const PHP_ROOT = path.resolve( LIBRARY_ROOT, '../php' ); +/** + * @param {string} resourcePath + */ function bundled( resourcePath ) { return { resource: 'bundled', path: resourcePath }; } +/** + * @param {Record} inputs + * @returns {Record} + */ export function createFinalBlueprint( inputs ) { return { $schema: inputs.dependencies.playground.blueprintSchema, @@ -91,6 +98,10 @@ export function createFinalBlueprint( inputs ) { }; } +/** + * @param {Record} inputs + * @param {Record} options + */ export async function packageFinalSnapshot( inputs, options ) { const work = path.resolve( options.workDirectory ); const output = path.resolve( options.output ); diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index a95b82ad6ba81..87d2382fc8762 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -5,6 +5,9 @@ const UPLOADS = 'https://uploads.github.com'; const BUILD_WORKFLOW = 'docs-playground-preview-build.yml'; const BUILD_JOB = 'Build Code Reference snapshot'; +/** + * @param {Record} values + */ function query( values ) { const parameters = new URLSearchParams(); for ( const [ name, value ] of Object.entries( values ) ) { @@ -16,12 +19,21 @@ function query( values ) { } export class GitHubApi { + /** + * @param {string} repository + * @param {string} token + * @param {(...args: any[]) => Promise} [fetchImplementation] + */ constructor( repository, token, fetchImplementation = globalThis.fetch ) { this.repository = repository; this.token = token; this.fetch = fetchImplementation; } + /** + * @param {string} url + * @param {Record} [options] + */ async request( url, options = {} ) { const headers = { Accept: 'application/vnd.github+json', @@ -45,12 +57,14 @@ export class GitHubApi { } if ( ! response.ok ) { const detail = await response.text(); - const error = new Error( - `GitHub API returned HTTP ${ - response.status - } for ${ url }: ${ detail.slice( 0, 300 ) }` + const error = Object.assign( + new Error( + `GitHub API returned HTTP ${ + response.status + } for ${ url }: ${ detail.slice( 0, 300 ) }` + ), + { status: response.status } ); - error.status = response.status; throw error; } if ( response.status === 204 ) { @@ -59,6 +73,10 @@ export class GitHubApi { return response.json(); } + /** + * @param {string} path + * @param {string | null} [field] + */ async pages( path, field = null ) { const values = []; for ( let page = 1; ; page++ ) { @@ -74,6 +92,9 @@ export class GitHubApi { } } + /** + * @param {number} runId + */ getRun( runId ) { return this.request( `/repos/${ this.repository }/actions/runs/${ runId }` @@ -87,10 +108,16 @@ export class GitHubApi { return reference.object?.sha || null; } + /** + * @param {number} number + */ getPullRequest( number ) { return this.request( `/repos/${ this.repository }/pulls/${ number }` ); } + /** + * @param {Record} run + */ async findPullRequestForRun( run ) { const owner = run.head_repository?.owner?.login; if ( ! owner || ! run.head_branch ) { @@ -120,6 +147,9 @@ export class GitHubApi { return matches[ 0 ]; } + /** + * @param {Record} run + */ async findLatestPreviewRun( run ) { const runs = await this.pages( `/repos/${ @@ -148,6 +178,9 @@ export class GitHubApi { return null; } + /** + * @param {Record} run + */ async latestPreviewRun( run ) { const latest = await this.findLatestPreviewRun( run ); if ( latest ) { @@ -180,6 +213,9 @@ export class GitHubApi { return this.getRun( latest.id ); } + /** + * @param {Record} run + */ async isSkippedPreviewBuild( run ) { const jobs = await this.pages( `/repos/${ this.repository }/actions/runs/${ run.id }/attempts/${ run.run_attempt }/jobs`, @@ -213,12 +249,21 @@ export class GitHubApi { } ); } + /** + * @param {number} releaseId + */ listReleaseAssets( releaseId ) { return this.pages( `/repos/${ this.repository }/releases/${ releaseId }/assets` ); } + /** + * @param {number} releaseId + * @param {string} name + * @param {Uint8Array} bytes + * @param {string} contentType + */ async uploadReleaseAsset( releaseId, name, bytes, contentType ) { const upload = () => this.request( @@ -237,7 +282,11 @@ export class GitHubApi { try { return await upload(); } catch ( error ) { - if ( error.status !== 422 ) { + if ( + ! ( error instanceof Error ) || + ! ( 'status' in error ) || + error.status !== 422 + ) { throw error; } const assets = await this.listReleaseAssets( releaseId ); @@ -250,6 +299,9 @@ export class GitHubApi { } } + /** + * @param {string} reference + */ getGitReference( reference ) { return this.request( `/repos/${ this.repository }/git/ref/${ reference }`, @@ -257,6 +309,9 @@ export class GitHubApi { ); } + /** + * @param {string} content + */ createGitBlob( content ) { return this.request( `/repos/${ this.repository }/git/blobs`, { method: 'POST', @@ -264,6 +319,10 @@ export class GitHubApi { } ); } + /** + * @param {string} path + * @param {string} blobSha + */ createGitTree( path, blobSha ) { return this.request( `/repos/${ this.repository }/git/trees`, { method: 'POST', @@ -280,6 +339,11 @@ export class GitHubApi { } ); } + /** + * @param {string} message + * @param {string} treeSha + * @param {string | null} [parentSha] + */ createGitCommit( message, treeSha, parentSha = null ) { return this.request( `/repos/${ this.repository }/git/commits`, { method: 'POST', @@ -291,6 +355,10 @@ export class GitHubApi { } ); } + /** + * @param {string} reference + * @param {string} sha + */ createGitReference( reference, sha ) { return this.request( `/repos/${ this.repository }/git/refs`, { method: 'POST', @@ -298,6 +366,10 @@ export class GitHubApi { } ); } + /** + * @param {string} reference + * @param {string} sha + */ updateGitReference( reference, sha ) { return this.request( `/repos/${ this.repository }/git/refs/${ reference }`, @@ -305,6 +377,9 @@ export class GitHubApi { ); } + /** + * @param {number} assetId + */ deleteReleaseAsset( assetId ) { return this.request( `/repos/${ this.repository }/releases/assets/${ assetId }`, @@ -312,6 +387,9 @@ export class GitHubApi { ); } + /** + * @param {string} ref + */ listActionCaches( ref ) { return this.pages( `/repos/${ this.repository }/actions/caches?${ query( { ref } ) }`, @@ -319,6 +397,9 @@ export class GitHubApi { ); } + /** + * @param {number} cacheId + */ deleteActionCache( cacheId ) { return this.request( `/repos/${ this.repository }/actions/caches/${ cacheId }`, @@ -326,6 +407,9 @@ export class GitHubApi { ); } + /** + * @param {number} pullRequestNumber + */ async findPreviewComment( pullRequestNumber ) { const comments = await this.pages( `/repos/${ this.repository }/issues/${ pullRequestNumber }/comments` @@ -339,6 +423,10 @@ export class GitHubApi { ); } + /** + * @param {number} pullRequestNumber + * @param {string} body + */ createComment( pullRequestNumber, body ) { return this.request( `/repos/${ this.repository }/issues/${ pullRequestNumber }/comments`, @@ -346,6 +434,10 @@ export class GitHubApi { ); } + /** + * @param {number} commentId + * @param {string} body + */ updateComment( commentId, body ) { return this.request( `/repos/${ this.repository }/issues/comments/${ commentId }`, @@ -353,6 +445,9 @@ export class GitHubApi { ); } + /** + * @param {number} pullRequestNumber + */ removeLabel( pullRequestNumber ) { return this.request( `/repos/${ this.repository }/issues/${ pullRequestNumber }/labels/docs-preview`, diff --git a/.github/scripts/docs-playground-preview/lib/inputs.mjs b/.github/scripts/docs-playground-preview/lib/inputs.mjs index d7c6c7460dd62..389866180d0a8 100644 --- a/.github/scripts/docs-playground-preview/lib/inputs.mjs +++ b/.github/scripts/docs-playground-preview/lib/inputs.mjs @@ -9,6 +9,9 @@ import { } from './config.mjs'; import { digestTree } from './files.mjs'; +/** + * @param {Record} options + */ export async function resolveBuildInputs( options ) { const repositoryRoot = path.resolve( options.repositoryRoot ); const configRoot = path.join( @@ -25,10 +28,16 @@ export async function resolveBuildInputs( options ) { const wordpress = await resolveWordPressBeta( options.fetchImplementation ); const configDigest = await digestTree( configRoot, + /** + * @param {string} relative + */ ( relative ) => ! relative.startsWith( 'node_modules/' ) ); const scriptsDigest = await digestTree( scriptsRoot, + /** + * @param {string} relative + */ ( relative ) => ! relative.startsWith( 'test/' ) ); const harnessDigest = await digestTreePair( configDigest, scriptsDigest ); @@ -56,6 +65,10 @@ export async function resolveBuildInputs( options ) { }; } +/** + * @param {string} first + * @param {string} second + */ async function digestTreePair( first, second ) { return createHash( 'sha256' ) .update( first ) @@ -63,6 +76,10 @@ async function digestTreePair( first, second ) { .digest( 'hex' ); } +/** + * @param {Record} inputs + * @param {string} filename + */ export async function writeResolvedInputs( inputs, filename ) { await mkdir( path.dirname( filename ), { recursive: true } ); await writeFile( filename, `${ JSON.stringify( inputs, null, 2 ) }\n` ); @@ -75,6 +92,9 @@ export async function writeResolvedInputs( inputs, filename ) { } } +/** + * @param {string} filename + */ export async function readResolvedInputs( filename ) { return JSON.parse( await readFile( filename, 'utf8' ) ); } diff --git a/.github/scripts/docs-playground-preview/lib/parser.mjs b/.github/scripts/docs-playground-preview/lib/parser.mjs index 5f1f346c2e4e3..24300e528d6a1 100644 --- a/.github/scripts/docs-playground-preview/lib/parser.mjs +++ b/.github/scripts/docs-playground-preview/lib/parser.mjs @@ -8,10 +8,17 @@ const HOOK_TYPE = /^(?:action|filter)(?:_(?:deprecated|reference))?$/; const IMPORT_SOURCE_ROOT = '/tmp/docs-preview-source'; const SAFE_VERSION_ROOT = '/tmp/docs-preview-version'; +/** + * @param {Record | null | undefined} value + */ function hooksIn( value ) { return Array.isArray( value?.hooks ) ? value.hooks : []; } +/** + * @param {any[]} hooks + * @param {Record} counts + */ function countHooks( hooks, counts ) { for ( const hook of hooks ) { if ( @@ -31,10 +38,15 @@ function countHooks( hooks, counts ) { } } +/** + * @param {any[]} records + * @param {Record} minimumSymbols + */ export function inspectParserRecords( records, minimumSymbols ) { if ( ! Array.isArray( records ) ) { throw new Error( 'Parser JSON must be an array.' ); } + /** @type {Record} */ const counts = { classes: 0, methods: 0, @@ -93,6 +105,9 @@ export function inspectParserRecords( records, minimumSymbols ) { return { records: records.length, counts, failures }; } +/** + * @param {Record} options + */ export async function generateParserJson( options ) { const runImplementation = options.runImplementation || run; const staged = await stageCorePhp( options.source, options.stagedSource ); diff --git a/.github/scripts/docs-playground-preview/lib/playground.mjs b/.github/scripts/docs-playground-preview/lib/playground.mjs index 0fbc15e8231d8..2b06b17ed7513 100644 --- a/.github/scripts/docs-playground-preview/lib/playground.mjs +++ b/.github/scripts/docs-playground-preview/lib/playground.mjs @@ -4,6 +4,9 @@ import { pathToFileURL } from 'node:url'; export const PLAYGROUND_BUILD_WORKERS = 1; export const PLAYGROUND_SERVER_WORKERS = 6; +/** + * @param {Record} options + */ export function createSnapshotArguments( options ) { return { ...options, @@ -12,11 +15,15 @@ export function createSnapshotArguments( options ) { }; } +/** + * @param {string} playgroundCli + * @param {Record} options + */ export async function buildSnapshot( playgroundCli, options ) { const modulePath = path.resolve( path.dirname( playgroundCli ), '../@wp-playground/cli/index.js' ); - const { runCLI } = await import( pathToFileURL( modulePath ) ); + const { runCLI } = await import( pathToFileURL( modulePath ).href ); await runCLI( createSnapshotArguments( options ) ); } diff --git a/.github/scripts/docs-playground-preview/lib/process.mjs b/.github/scripts/docs-playground-preview/lib/process.mjs index b8c899a342052..aad8f4e8c8747 100644 --- a/.github/scripts/docs-playground-preview/lib/process.mjs +++ b/.github/scripts/docs-playground-preview/lib/process.mjs @@ -1,6 +1,11 @@ import { spawn } from 'node:child_process'; import { writeFile } from 'node:fs/promises'; +/** + * @param {string} command + * @param {string[]} args + * @param {{allowFailure?: boolean, capture?: boolean, cwd?: string, env?: NodeJS.ProcessEnv, label?: string, logFile?: string, quiet?: boolean}} [options] + */ export async function run( command, args, options = {} ) { const capture = options.capture || Boolean( options.logFile ); if ( ! options.quiet ) { diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs index 53f1f7792b76c..0e4c5f5231fdb 100644 --- a/.github/scripts/docs-playground-preview/lib/publication.mjs +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -10,6 +10,10 @@ const FULL_COMMIT = /^[0-9a-f]{40}$/; const FULL_DIGEST = /^[0-9a-f]{64}$/; const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; +/** + * @param {unknown} value + * @param {string} label + */ function positiveInteger( value, label ) { const number = Number( value ); if ( ! Number.isSafeInteger( number ) || number < 1 ) { @@ -18,18 +22,29 @@ function positiveInteger( value, label ) { return number; } +/** + * @param {string} repository + * @param {string} label + */ function assertRepository( repository, label ) { if ( typeof repository !== 'string' || ! REPOSITORY.test( repository ) ) { throw new Error( `${ label } must be an owner/repository.` ); } } +/** + * @param {string} sha + * @param {string} label + */ function assertCommit( sha, label ) { if ( typeof sha !== 'string' || ! FULL_COMMIT.test( sha ) ) { throw new Error( `${ label } must be a full lowercase commit hash.` ); } } +/** + * @param {Record} identity + */ export function snapshotAssetName( identity ) { const pullRequest = positiveInteger( identity.pullRequestNumber, @@ -44,6 +59,9 @@ export function snapshotAssetName( identity ) { return `code-reference-pr-${ pullRequest }-${ identity.sourceSha }-${ runId }-${ attempt }.zip`; } +/** + * @param {string} snapshotName + */ export function metadataAssetName( snapshotName ) { if ( typeof snapshotName !== 'string' || @@ -54,6 +72,10 @@ export function metadataAssetName( snapshotName ) { return `${ snapshotName.slice( 0, -4 ) }.json`; } +/** + * @param {string} repository + * @param {string} assetName + */ export function releaseAssetUrl( repository, assetName ) { assertRepository( repository, 'repository' ); if ( @@ -65,6 +87,9 @@ export function releaseAssetUrl( repository, assetName ) { return `https://github.com/${ repository }/releases/download/${ RELEASE_TAG }/${ assetName }`; } +/** + * @param {string} publicUrl + */ export function corsProxyUrl( publicUrl ) { const parsed = new URL( publicUrl ); if ( @@ -78,6 +103,10 @@ export function corsProxyUrl( publicUrl ) { return `${ CORS_PROXY }${ publicUrl }`; } +/** + * @param {string} snapshotUrl + * @param {Record} runtime + */ export function createLaunchBlueprint( snapshotUrl, runtime ) { return { $schema: runtime.blueprintSchema, @@ -104,6 +133,10 @@ export function createLaunchBlueprint( snapshotUrl, runtime ) { }; } +/** + * @param {string} snapshotUrl + * @param {Record} runtime + */ export function playgroundUrl( snapshotUrl, runtime ) { const blueprint = JSON.stringify( createLaunchBlueprint( snapshotUrl, runtime ) @@ -113,6 +146,11 @@ export function playgroundUrl( snapshotUrl, runtime ) { ) }`; } +/** + * @param {string} publicUrl + * @param {Record} expected + * @param {(...args: any[]) => Promise} [fetchImplementation] + */ export async function validatePublicSnapshot( publicUrl, expected, @@ -162,6 +200,10 @@ export async function validatePublicSnapshot( return { bytes: bytes.byteLength, sha256: digest }; } +/** + * @param {Record} metadata + * @param {Record} expected + */ export function validatePublishedSnapshotMetadata( metadata, expected ) { if ( ! metadata || @@ -229,6 +271,10 @@ export function validatePublishedSnapshotMetadata( metadata, expected ) { return metadata; } +/** + * @param {Record} metadata + * @param {Record} expected + */ export function validateReusableMetadata( metadata, expected ) { validatePublishedSnapshotMetadata( metadata, { ...expected, @@ -250,6 +296,11 @@ export function validateReusableMetadata( metadata, expected ) { return metadata; } +/** + * @param {Record} published + * @param {Record} identity + * @returns {Record} + */ export function createReuseHandoff( published, identity ) { validateReusableMetadata( published, { ...identity, diff --git a/.github/scripts/docs-playground-preview/lib/published.mjs b/.github/scripts/docs-playground-preview/lib/published.mjs index 99e9750fc26b8..cc77e2c69ae88 100644 --- a/.github/scripts/docs-playground-preview/lib/published.mjs +++ b/.github/scripts/docs-playground-preview/lib/published.mjs @@ -11,6 +11,10 @@ import { const BLUEPRINT_SCHEMA = 'https://playground.wordpress.net/blueprint-schema.json'; +/** + * @param {Record} asset + * @param {(...args: any[]) => any} fetchImplementation + */ async function fetchPublishedMetadata( asset, fetchImplementation ) { const response = await fetchImplementation( asset.browser_download_url ); if ( response.status !== 200 ) { @@ -21,6 +25,11 @@ async function fetchPublishedMetadata( asset, fetchImplementation ) { return response.json(); } +/** + * @param {Record} metadata + * @param {string} repository + * @param {Record} snapshotAsset + */ function validatePublishedFields( metadata, repository, snapshotAsset ) { const snapshotUrl = releaseAssetUrl( repository, snapshotAsset.name ); if ( @@ -42,6 +51,13 @@ function validatePublishedFields( metadata, repository, snapshotAsset ) { } } +/** + * @param {string} repository + * @param {number} pullRequestNumber + * @param {Record} metadataAsset + * @param {Record} snapshotAsset + * @param {Record} options + */ export async function loadPublishedPreview( repository, pullRequestNumber, @@ -80,6 +96,9 @@ export async function loadPublishedPreview( return metadata; } +/** + * @param {Record} session + */ export async function findPreviousPreview( session, excluded = new Set() ) { const release = await session.api.getRelease(); if ( ! release ) { @@ -89,13 +108,19 @@ export async function findPreviousPreview( session, excluded = new Set() ) { const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; const candidates = assets .filter( + /** + * @param {Record} asset + */ ( asset ) => asset.name.startsWith( prefix ) && asset.name.endsWith( '.json' ) && ! excluded.has( asset.name ) ) - .sort( ( left, right ) => - right.created_at.localeCompare( left.created_at ) + .sort( + /** @param {Record} left @param {Record} right */ ( + left, + right + ) => right.created_at.localeCompare( left.created_at ) ); for ( const metadataAsset of candidates ) { try { @@ -104,6 +129,9 @@ export async function findPreviousPreview( session, excluded = new Set() ) { session.fetchImplementation ); const snapshotAsset = assets.find( + /** + * @param {Record} asset + */ ( asset ) => asset.name === published.snapshotFilename && ! excluded.has( asset.name ) @@ -124,7 +152,9 @@ export async function findPreviousPreview( session, excluded = new Set() ) { ); } catch ( error ) { session.warning( - `Cannot retain ${ metadataAsset.name }: ${ error.message }` + `Cannot retain ${ metadataAsset.name }: ${ + error instanceof Error ? error.message : String( error ) + }` ); } } diff --git a/.github/scripts/docs-playground-preview/lib/publisher.mjs b/.github/scripts/docs-playground-preview/lib/publisher.mjs index 22e87dfb29f71..8ea8b09dd794d 100644 --- a/.github/scripts/docs-playground-preview/lib/publisher.mjs +++ b/.github/scripts/docs-playground-preview/lib/publisher.mjs @@ -21,6 +21,10 @@ const FULL_DIGEST = /^[0-9a-f]{64}$/; const BLUEPRINT_SCHEMA = 'https://playground.wordpress.net/blueprint-schema.json'; +/** + * @param {unknown} value + * @param {string} label + */ function positiveInteger( value, label ) { const number = Number( value ); if ( ! Number.isSafeInteger( number ) || number < 1 ) { @@ -29,6 +33,10 @@ function positiveInteger( value, label ) { return number; } +/** + * @param {unknown} value + * @param {string} label + */ function timestamp( value, label ) { if ( typeof value !== 'string' || @@ -40,10 +48,17 @@ function timestamp( value, label ) { return value; } +/** + * @param {Record | null | undefined} value + */ function headRepository( value ) { return value?.full_name || value?.repo?.full_name || null; } +/** + * @param {Record} context + * @returns {Record} + */ export function validatePublicationContext( context ) { if ( ! isDeploymentEnabled( context.repository, context.stagingVariable ) @@ -111,6 +126,9 @@ export function validatePublicationContext( context ) { }; } +/** + * @param {Record} context + */ export function assertLatestAuthorized( context ) { const current = validatePublicationContext( context ); if ( @@ -123,6 +141,9 @@ export function assertLatestAuthorized( context ) { throw new Error( 'The pull request is no longer open.' ); } const hasLabel = current.pullRequest.labels?.some( + /** + * @param {Record} label + */ ( label ) => label.name === 'docs-preview' ); if ( ! hasLabel && current.workflowRunAttempt === 1 ) { @@ -131,6 +152,10 @@ export function assertLatestAuthorized( context ) { return current; } +/** + * @param {Record} metadata + * @param {Record} context + */ function validateCommonHandoff( metadata, context ) { if ( ! metadata || @@ -155,6 +180,9 @@ function validateCommonHandoff( metadata, context ) { timestamp( metadata.generationTimestamp, 'Generation timestamp' ); } +/** + * @param {Record} metadata + */ function validateSnapshotIdentity( metadata ) { if ( ! Number.isSafeInteger( metadata.snapshotBytes ) || @@ -168,6 +196,10 @@ function validateSnapshotIdentity( metadata ) { } } +/** + * @param {Record} metadata + * @param {Record} rawContext + */ export function inspectHandoff( metadata, rawContext ) { const context = validatePublicationContext( rawContext ); validateCommonHandoff( metadata, context ); @@ -210,6 +242,10 @@ export function inspectHandoff( metadata, rawContext ) { return { kind: 'candidate', metadata, context }; } +/** + * @param {Record} metadata + * @param {string} filename + */ export async function validateCandidateFile( metadata, filename ) { if ( path.basename( filename ) !== metadata.snapshotFilename ) { throw new Error( @@ -227,6 +263,12 @@ export async function validateCandidateFile( metadata, filename ) { return { bytes: candidate.size, sha256: digest }; } +/** + * @param {Record} metadata + * @param {string} repository + * @param {string} publishedAt + * @returns {Record} + */ export function createPublishedMetadata( metadata, repository, publishedAt ) { timestamp( publishedAt, 'Publication timestamp' ); const snapshotUrl = releaseAssetUrl( @@ -248,10 +290,17 @@ export function createPublishedMetadata( metadata, repository, publishedAt ) { }; } +/** + * @param {string} repository + * @param {string} sha + */ function commitLink( repository, sha ) { return `[${ sha }](https://github.com/${ repository }/commit/${ sha })`; } +/** + * @param {Record} previous + */ function previousLink( previous ) { if ( ! previous ) { return ''; @@ -264,13 +313,19 @@ function previousLink( previous ) { ) }.`; } -function commentHeader( source ) { +/** + * @param {Record | null} [source] + */ +function commentHeader( source = null ) { const identity = source ? `\n` : ''; return `${ COMMENT_MARKER }${ identity }\n## Code Reference documentation preview`; } +/** + * @param {unknown} body + */ export function readPreviewCommentSource( body ) { if ( typeof body !== 'string' ) { return null; @@ -281,6 +336,9 @@ export function readPreviewCommentSource( body ) { return match ? { repository: match[ 1 ], sha: match[ 2 ] } : null; } +/** + * @param {unknown} body + */ export function readPreviewCommentSuccess( body ) { if ( typeof body !== 'string' ) { return null; @@ -307,6 +365,9 @@ export function readPreviewCommentSuccess( body ) { }; } +/** + * @param {Record} state + */ export function renderPreviewComment( state ) { if ( state.status === 'ready' ) { const header = commentHeader( { diff --git a/.github/scripts/docs-playground-preview/lib/runtime.mjs b/.github/scripts/docs-playground-preview/lib/runtime.mjs index a37701e0e3e67..ab58930be4486 100644 --- a/.github/scripts/docs-playground-preview/lib/runtime.mjs +++ b/.github/scripts/docs-playground-preview/lib/runtime.mjs @@ -3,10 +3,16 @@ const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; const RUN_URL = /^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/actions\/runs\/\d+$/; +/** + * @param {unknown} value + */ function phpString( value ) { return JSON.stringify( value ); } +/** + * @param {Record} provenance + */ export function validateProvenance( provenance ) { if ( ! REPOSITORY.test( provenance?.sourceRepository || '' ) ) { throw new Error( 'Preview provenance repository is invalid.' ); @@ -29,6 +35,9 @@ export function validateProvenance( provenance ) { return provenance; } +/** + * @param {Record} candidate + */ export function renderRuntimePlugin( candidate ) { const provenance = validateProvenance( candidate ); const runUrl = diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs index def0b455bf865..4ea55b44c31dc 100644 --- a/.github/scripts/docs-playground-preview/lib/trunk.mjs +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -21,6 +21,10 @@ const BLUEPRINT_SCHEMA = const FULL_COMMIT = /^[0-9a-f]{40}$/; const MAXIMUM_BLUEPRINT_BYTES = 65536; +/** + * @param {unknown} value + * @param {string} label + */ function positiveInteger( value, label ) { const number = Number( value ); if ( ! Number.isSafeInteger( number ) || number < 1 ) { @@ -29,6 +33,10 @@ function positiveInteger( value, label ) { return number; } +/** + * @param {unknown} value + * @param {string} label + */ function timestamp( value, label ) { if ( typeof value !== 'string' || @@ -40,12 +48,16 @@ function timestamp( value, label ) { return value; } +/** + * @param {string} message + */ function supersededTrunkError( message ) { - const error = new Error( message ); - error.trunkRunSuperseded = true; - return error; + return Object.assign( new Error( message ), { trunkRunSuperseded: true } ); } +/** + * @param {Record} identity + */ export function trunkSnapshotAssetName( identity ) { if ( ! FULL_COMMIT.test( identity.sourceSha || '' ) ) { throw new Error( 'sourceSha must be a full lowercase commit hash.' ); @@ -58,10 +70,17 @@ export function trunkSnapshotAssetName( identity ) { return `code-reference-trunk-${ identity.sourceSha }-${ runId }-${ attempt }.zip`; } +/** + * @param {string} repository + */ export function trunkStableBlueprintUrl( repository ) { return `https://raw.githubusercontent.com/${ repository }/docs-preview-code-reference/${ TRUNK_POINTER_ASSET }`; } +/** + * @param {string} repository + * @param {string} commitSha + */ export function trunkBlueprintCommitUrl( repository, commitSha ) { if ( ! FULL_COMMIT.test( commitSha || '' ) ) { throw new Error( 'commitSha must be a full lowercase commit hash.' ); @@ -69,12 +88,18 @@ export function trunkBlueprintCommitUrl( repository, commitSha ) { return `https://raw.githubusercontent.com/${ repository }/${ commitSha }/${ TRUNK_POINTER_ASSET }`; } +/** + * @param {string} repository + */ export function trunkPlaygroundUrl( repository ) { return `${ PLAYGROUND_ORIGIN }/?blueprint-url=${ encodeURIComponent( corsProxyUrl( trunkStableBlueprintUrl( repository ) ) ) }`; } +/** + * @param {Record} context + */ export function validateTrunkPublicationContext( context ) { if ( ! isDeploymentEnabled( context.repository, context.stagingVariable ) @@ -126,6 +151,9 @@ export function validateTrunkPublicationContext( context ) { }; } +/** + * @param {Record} context + */ export function assertLatestTrunkAuthorized( context ) { const current = validateTrunkPublicationContext( context ); if ( @@ -139,6 +167,10 @@ export function assertLatestTrunkAuthorized( context ) { return current; } +/** + * @param {Record} metadata + * @param {Record} context + */ function validateCommonHandoff( metadata, context ) { if ( ! metadata || @@ -161,6 +193,10 @@ function validateCommonHandoff( metadata, context ) { timestamp( metadata.generationTimestamp, 'Generation timestamp' ); } +/** + * @param {Record} metadata + * @param {Record} rawContext + */ export function inspectTrunkHandoff( metadata, rawContext ) { const context = validateTrunkPublicationContext( rawContext ); validateCommonHandoff( metadata, context ); @@ -191,6 +227,11 @@ export function inspectTrunkHandoff( metadata, rawContext ) { return { kind: 'candidate', metadata, context }; } +/** + * @param {Record} metadata + * @param {string} repository + * @param {string} publishedAt + */ export function createTrunkPublishedMetadata( metadata, repository, @@ -218,6 +259,11 @@ export function createTrunkPublishedMetadata( }; } +/** + * @param {Record} metadata + * @param {string} repository + * @param {string} sourceSha + */ export function validatePublishedTrunkMetadata( metadata, repository, @@ -264,6 +310,9 @@ export function validatePublishedTrunkMetadata( return metadata; } +/** + * @param {Record} metadata + */ export function createTrunkBlueprint( metadata ) { const blueprint = createLaunchBlueprint( metadata.publication.snapshotUrl, { blueprintSchema: BLUEPRINT_SCHEMA, @@ -274,6 +323,10 @@ export function createTrunkBlueprint( metadata ) { return blueprint; } +/** + * @param {string} publicUrl + * @param {(...args: any[]) => Promise} [fetchImplementation] + */ export async function readPublicBlueprint( publicUrl, fetchImplementation = globalThis.fetch @@ -306,6 +359,11 @@ export async function readPublicBlueprint( return blueprint; } +/** + * @param {string} publicUrl + * @param {Record} expected + * @param {(...args: any[]) => Promise} [fetchImplementation] + */ export async function validatePublicBlueprint( publicUrl, expected, diff --git a/.github/scripts/docs-playground-preview/lib/validate.mjs b/.github/scripts/docs-playground-preview/lib/validate.mjs index 0e23b74433263..eef9a4c73ce71 100644 --- a/.github/scripts/docs-playground-preview/lib/validate.mjs +++ b/.github/scripts/docs-playground-preview/lib/validate.mjs @@ -7,10 +7,16 @@ import { PLAYGROUND_SERVER_WORKERS } from './playground.mjs'; const BANNER_ID = 'wporg-code-reference-preview-provenance'; +/** + * @param {string} resourcePath + */ function bundled( resourcePath ) { return { resource: 'bundled', path: resourcePath }; } +/** + * @param {Record} inputs + */ export function createValidationBlueprint( inputs ) { return { $schema: inputs.dependencies.playground.blueprintSchema, @@ -31,6 +37,9 @@ export function createValidationBlueprint( inputs ) { }; } +/** + * @param {number} milliseconds + */ function delay( milliseconds ) { return new Promise( ( resolve ) => setTimeout( resolve, milliseconds ) ); } @@ -39,13 +48,21 @@ async function availablePort() { const server = createServer(); await new Promise( ( resolve, reject ) => { server.once( 'error', reject ); - server.listen( 0, '127.0.0.1', resolve ); + server.listen( 0, '127.0.0.1', () => resolve( undefined ) ); } ); - const port = server.address().port; + const address = server.address(); + if ( ! address || typeof address === 'string' ) { + throw new Error( 'Validation server did not bind a TCP port.' ); + } + const port = address.port; await new Promise( ( resolve ) => server.close( resolve ) ); return port; } +/** + * @param {string} command + * @param {string[]} args + */ function startServer( command, args ) { const child = spawn( command, args, { stdio: [ 'ignore', 'pipe', 'pipe' ], @@ -64,6 +81,12 @@ function startServer( command, args ) { return { child, closed, output: () => output }; } +/** + * @param {Record} inputs + * @param {string} blueprint + * @param {string} baseUrl + * @param {number} port + */ export function createValidationServerArguments( inputs, blueprint, @@ -90,6 +113,9 @@ export function createValidationServerArguments( ]; } +/** + * @param {Record} server + */ async function stopServer( server ) { if ( server.child.exitCode !== null || server.child.signalCode !== null ) { return; @@ -105,6 +131,11 @@ async function stopServer( server ) { } } +/** + * @param {string} baseUrl + * @param {Record} server + * @param {(...args: any[]) => any} fetchImplementation + */ async function waitForBoot( baseUrl, server, fetchImplementation ) { const deadline = Date.now() + 120000; while ( Date.now() < deadline ) { @@ -135,6 +166,11 @@ async function waitForBoot( baseUrl, server, fetchImplementation ) { ); } +/** + * @param {Record} inputs + * @param {Record} options + * @param {(...args: any[]) => any} inspect + */ async function withPlaygroundServer( inputs, options, inspect ) { const work = path.resolve( options.workDirectory ); await rm( work, { recursive: true, force: true } ); @@ -160,6 +196,10 @@ async function withPlaygroundServer( inputs, options, inspect ) { } } +/** + * @param {Record} actual + * @param {Record} expected + */ function provenanceFailure( actual, expected ) { for ( const name of [ 'sourceRepository', @@ -174,6 +214,12 @@ function provenanceFailure( actual, expected ) { return null; } +/** + * @param {string} name + * @param {string} body + * @param {Record} provenance + * @param {any[]} failures + */ function checkBanner( name, body, provenance, failures ) { const timestamp = provenance.generationTimestamp .slice( 0, 19 ) @@ -196,10 +242,15 @@ function checkBanner( name, body, provenance, failures ) { } } +/** + * @param {Record} inputs + * @param {Record} options + */ export async function inspectSnapshotBehavior( inputs, options ) { const failures = []; + /** @type {Record} */ const checks = {}; - const request = async ( route ) => { + const request = /** @param {string} route */ async ( route ) => { const response = await options.fetchImplementation( `${ options.baseUrl }${ route }` ); @@ -219,7 +270,11 @@ export async function inspectSnapshotBehavior( inputs, options ) { failures.push( `Health route returned HTTP ${ response.status }.` ); } } catch ( error ) { - failures.push( `Health route failed: ${ error.message }` ); + failures.push( + `Health route failed: ${ + error instanceof Error ? error.message : String( error ) + }` + ); } if ( health ) { const mismatch = provenanceFailure( @@ -276,7 +331,11 @@ export async function inspectSnapshotBehavior( inputs, options ) { } checkBanner( name, response.body, options.provenance, failures ); } catch ( error ) { - failures.push( `${ name } route failed: ${ error.message }` ); + failures.push( + `${ name } route failed: ${ + error instanceof Error ? error.message : String( error ) + }` + ); } } @@ -296,7 +355,9 @@ export async function inspectSnapshotBehavior( inputs, options ) { checkBanner( 'search', response.body, options.provenance, failures ); } catch ( error ) { failures.push( - `Local Code Reference search failed: ${ error.message }` + `Local Code Reference search failed: ${ + error instanceof Error ? error.message : String( error ) + }` ); } @@ -306,12 +367,19 @@ export async function inspectSnapshotBehavior( inputs, options ) { return { failures, checks }; } +/** + * @param {Record} inputs + * @param {Record} options + */ export async function validateSnapshot( inputs, options ) { const fetchImplementation = options.fetchImplementation || globalThis.fetch; try { return await ( options.serveImplementation || withPlaygroundServer )( inputs, { ...options, fetchImplementation }, + /** + * @param {string} baseUrl + */ ( baseUrl ) => inspectSnapshotBehavior( inputs, { ...options, @@ -321,7 +389,11 @@ export async function validateSnapshot( inputs, options ) { ); } catch ( error ) { return { - failures: [ `Playground boot failed: ${ error.message }` ], + failures: [ + `Playground boot failed: ${ + error instanceof Error ? error.message : String( error ) + }`, + ], checks: {}, }; } diff --git a/.github/scripts/docs-playground-preview/lifecycle.mjs b/.github/scripts/docs-playground-preview/lifecycle.mjs index 29979d8342ce1..eaa80f2423863 100644 --- a/.github/scripts/docs-playground-preview/lifecycle.mjs +++ b/.github/scripts/docs-playground-preview/lifecycle.mjs @@ -17,6 +17,9 @@ const CACHE_PREFIX = 'docs-preview-base-'; class LifecycleSuperseded extends Error {} +/** + * @param {unknown} body + */ function isTerminalComment( body ) { return ( typeof body === 'string' && @@ -25,6 +28,10 @@ function isTerminalComment( body ) { ); } +/** + * @param {unknown} value + * @param {string} label + */ function positiveInteger( value, label ) { const number = Number( value ); if ( ! Number.isSafeInteger( number ) || number < 1 ) { @@ -33,6 +40,9 @@ function positiveInteger( value, label ) { return number; } +/** + * @param {Record} options + */ function lifecycleContext( options ) { if ( ! isDeploymentEnabled( options.repository, options.stagingVariable ) @@ -68,6 +78,12 @@ function lifecycleContext( options ) { }; } +/** + * @param {Record} context + * @param {Record} pullRequest + * @param {string} state + * @param {boolean} labelMustBeAbsent + */ function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { if ( pullRequest.number !== context.pullRequestNumber || @@ -78,6 +94,9 @@ function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { pullRequest.head.repo?.full_name !== context.sourceRepository ) || ( labelMustBeAbsent && pullRequest.labels?.some( + /** + * @param {Record} label + */ ( label ) => label.name === 'docs-preview' ) ) ) { @@ -86,6 +105,9 @@ function assertCurrent( context, pullRequest, state, labelMustBeAbsent ) { return pullRequest; } +/** + * @param {Record} options + */ function sessionFrom( options ) { const context = lifecycleContext( options ); const api = @@ -95,7 +117,14 @@ function sessionFrom( options ) { options.token, options.fetchImplementation ); - const authorize = async ( state, labelMustBeAbsent = false ) => { + /** @type {(message: string) => unknown} */ + const warning = + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ); + const authorize = /** @param {string} state */ async ( + state, + labelMustBeAbsent = false + ) => { const pullRequest = await api.getPullRequest( context.pullRequestNumber ); @@ -107,7 +136,9 @@ function sessionFrom( options ) { labelMustBeAbsent ); } catch ( error ) { - throw new LifecycleSuperseded( error.message ); + throw new LifecycleSuperseded( + error instanceof Error ? error.message : String( error ) + ); } }; return { @@ -115,13 +146,15 @@ function sessionFrom( options ) { context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: - options.warning || - ( ( message ) => process.stderr.write( `${ message }\n` ) ), + warning, authorize, }; } +/** + * @param {Record} session + * @param {Record} expectedComment + */ async function authorizeStaleMutation( session, expectedComment ) { await session.authorize( 'open', true ); const currentComment = await session.api.findPreviewComment( @@ -137,6 +170,9 @@ async function authorizeStaleMutation( session, expectedComment ) { } } +/** + * @param {Record} session + */ async function markStale( session ) { try { return await markStaleAuthorized( session ); @@ -148,6 +184,9 @@ async function markStale( session ) { } } +/** + * @param {Record} session + */ async function markStaleAuthorized( session ) { await session.authorize( 'open', true ); const comment = await session.api.findPreviewComment( @@ -160,7 +199,7 @@ async function markStaleAuthorized( session ) { if ( isTerminalComment( comment.body ) && commentSource?.repository === session.context.sourceRepository && - commentSource.sha === session.context.sourceSha + commentSource?.sha === session.context.sourceSha ) { return { status: 'ignored' }; } @@ -199,6 +238,9 @@ async function markStaleAuthorized( session ) { return { status: 'stale' }; } +/** + * @param {any[]} operations + */ async function settle( operations ) { const errors = []; for ( const operation of operations ) { @@ -214,6 +256,9 @@ async function settle( operations ) { return { errors, superseded: false }; } +/** + * @param {Record} session + */ async function expire( session ) { try { await session.authorize( 'closed' ); @@ -227,11 +272,17 @@ async function expire( session ) { const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; const assets = release ? ( await session.api.listReleaseAssets( release.id ) ).filter( + /** + * @param {Record} asset + */ ( asset ) => asset.name.startsWith( prefix ) ) : []; const cacheRef = `refs/pull/${ session.context.pullRequestNumber }/merge`; const caches = ( await session.api.listActionCaches( cacheRef ) ).filter( + /** + * @param {Record} cache + */ ( cache ) => cache.ref === cacheRef && cache.key.startsWith( CACHE_PREFIX ) ); @@ -239,17 +290,22 @@ async function expire( session ) { session.context.pullRequestNumber ); const assetCleanup = await settle( - assets.map( ( asset ) => async () => { - await session.authorize( 'closed' ); - await session.api.deleteReleaseAsset( asset.id ); - } ) + assets.map( + /** @param {Record} asset */ ( asset ) => async () => { + await session.authorize( 'closed' ); + await session.api.deleteReleaseAsset( asset.id ); + } + ) ); const cacheCleanup = await settle( - caches.map( ( cache ) => async () => { - await session.authorize( 'closed' ); - await session.api.deleteActionCache( cache.id ); - } ) + caches.map( + /** @param {Record} cache */ ( cache ) => async () => { + await session.authorize( 'closed' ); + await session.api.deleteActionCache( cache.id ); + } + ) ); + /** @type {{errors: unknown[], superseded: boolean}} */ let commentCleanup = { errors: [], superseded: false }; if ( comment && @@ -288,6 +344,9 @@ async function expire( session ) { }; } +/** + * @param {Record} options + */ export async function managePullRequest( options ) { const session = sessionFrom( options ); return session.context.action === 'synchronize' @@ -296,7 +355,11 @@ export async function managePullRequest( options ) { } async function main() { - const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const eventPath = process.env.GITHUB_EVENT_PATH; + if ( ! eventPath ) { + throw new Error( 'GITHUB_EVENT_PATH is required.' ); + } + const event = JSON.parse( await readFile( eventPath, 'utf8' ) ); const result = await managePullRequest( { repository: process.env.GITHUB_REPOSITORY, stagingVariable: process.env.DOCS_PREVIEW_STAGING, diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index 574ca207f75bd..7d343366f37d9 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -31,12 +31,36 @@ const TRUNK_POINTER_BRANCH = TRUNK_POINTER_REF.replace( /^heads\//, '' ); const TRUNK_GENERATION_ASSET = /^(code-reference-trunk-[0-9a-f]{40}-(\d+)-(\d+))\.(?:zip|json)$/; +/** + * @param {unknown} error + */ +function errorMessage( error ) { + return error instanceof Error ? error.message : String( error ); +} + +/** + * @param {unknown} error + * @param {string} property + */ +function errorFlag( error, property ) { + return ( + error instanceof Error && + /** @type {any} */ ( error )[ property ] === true + ); +} + +/** + * @param {string} directory + */ async function readHandoff( directory ) { return JSON.parse( await readFile( path.join( directory, 'build.json' ), 'utf8' ) ); } +/** + * @param {Record} options + */ async function establishSession( options ) { const api = options.api || @@ -54,18 +78,21 @@ async function establishSession( options ) { run, }; const context = validateTrunkPublicationContext( base ); + /** @type {(message: string) => unknown} */ const notice = options.notice || ( ( message ) => process.stdout.write( `${ message }\n` ) ); + /** @type {(message: string) => unknown} */ + const warning = + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ); let staleHeadReported = false; return { api, context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: - options.warning || - ( ( message ) => process.stderr.write( `${ message }\n` ) ), + warning, now: options.now || ( () => new Date().toISOString() ), handoffDirectory: path.resolve( options.handoffDirectory ), authorize: async () => { @@ -81,7 +108,7 @@ async function establishSession( options ) { trunkHeadSha, } ); } catch ( error ) { - throw new SupersededTrunkRun( error.message ); + throw new SupersededTrunkRun( errorMessage( error ) ); } if ( trunkHeadSha !== current.sourceSha && ! staleHeadReported ) { staleHeadReported = true; @@ -94,6 +121,9 @@ async function establishSession( options ) { }; } +/** + * @param {Record} session + */ async function ensureRelease( session ) { let release = await session.api.getRelease(); if ( release ) { @@ -111,6 +141,11 @@ async function ensureRelease( session ) { return release; } +/** + * @param {Record} session + * @param {Record} asset + * @param {Record} expected + */ async function validatePublicMetadata( session, asset, expected ) { const response = await session.fetchImplementation( asset.browser_download_url @@ -133,6 +168,10 @@ async function validatePublicMetadata( session, asset, expected ) { return metadata; } +/** + * @param {Record} session + * @param {Record} expected + */ async function validateStablePointerContent( session, expected ) { // The raw CDN caches the branch-path Blueprint for minutes, so the // post-move read-back must use the authoritative contents API instead. @@ -158,22 +197,36 @@ async function validateStablePointerContent( session, expected ) { return blueprint; } +/** + * @param {Record} session + * @param {any[]} uploaded + */ async function cleanupUploaded( session, uploaded ) { for ( const asset of uploaded ) { try { await session.api.deleteReleaseAsset( asset.id ); } catch ( error ) { session.warning( - `Cannot remove failed trunk candidate ${ asset.name }: ${ error.message }` + `Cannot remove failed trunk candidate ${ + asset.name + }: ${ errorMessage( error ) }` ); } } } +/** + * @param {Record | null} reference + */ function referenceSha( reference ) { return reference?.object?.sha || null; } +/** + * @param {Record} session + * @param {Record} previousRef + * @param {Record} blueprint + */ async function createPointerCommit( session, previousRef, blueprint ) { const content = `${ JSON.stringify( blueprint, null, 2 ) }\n`; await session.authorize(); @@ -197,6 +250,11 @@ async function createPointerCommit( session, previousRef, blueprint ) { return commit; } +/** + * @param {Record} session + * @param {string} previousSha + * @param {string} candidateSha + */ async function resolvePointerMutation( session, previousSha, candidateSha ) { let current; try { @@ -204,8 +262,10 @@ async function resolvePointerMutation( session, previousSha, candidateSha ) { await session.api.getGitReference( TRUNK_POINTER_REF ) ); } catch ( error ) { - error.pointerStateUnknown = true; - throw error; + throw Object.assign( + error instanceof Error ? error : new Error( String( error ) ), + { pointerStateUnknown: true } + ); } if ( current === candidateSha ) { return true; @@ -213,11 +273,18 @@ async function resolvePointerMutation( session, previousSha, candidateSha ) { if ( current === previousSha ) { return false; } - const error = new Error( 'The stable trunk pointer has unknown state.' ); - error.pointerStateUnknown = true; - throw error; + throw Object.assign( + new Error( 'The stable trunk pointer has unknown state.' ), + { pointerStateUnknown: true } + ); } +/** + * @param {Record} session + * @param {Record} previousRef + * @param {Record} commit + * @param {Record} transaction + */ async function moveStablePointer( session, previousRef, commit, transaction ) { const previousSha = referenceSha( previousRef ); let mutationError = null; @@ -243,15 +310,23 @@ async function moveStablePointer( session, previousRef, commit, transaction ) { commit.sha ); if ( ! moved ) { - const error = - mutationError || - new Error( 'The stable trunk pointer mutation has unknown state.' ); - error.pointerStateUnknown = true; - throw error; + throw Object.assign( + mutationError instanceof Error + ? mutationError + : new Error( + 'The stable trunk pointer mutation has unknown state.' + ), + { pointerStateUnknown: true } + ); } transaction.pointerPublished = true; } +/** + * @param {Record} session + * @param {Record} release + * @param {Set} keepIds + */ async function cleanupOldTrunkAssets( session, release, keepIds ) { const assets = await session.api.listReleaseAssets( release.id ); const generations = new Map(); @@ -284,6 +359,12 @@ async function cleanupOldTrunkAssets( session, release, keepIds ) { } } +/** + * @param {Record} session + * @param {Record} metadata + * @param {any[]} uploaded + * @param {Record} transaction + */ async function publishCandidate( session, metadata, uploaded, transaction ) { const candidateFile = path.join( session.handoffDirectory, @@ -346,16 +427,20 @@ async function publishCandidate( session, metadata, uploaded, transaction ) { return { status: 'ready', published, pointerCommit: pointerCommit.sha }; } +/** + * @param {Record} options + */ export async function publishTrunk( options ) { let session; try { session = await establishSession( options ); } catch ( error ) { - if ( error.trunkRunSuperseded === true ) { + if ( errorFlag( error, 'trunkRunSuperseded' ) ) { return { status: 'superseded' }; } throw error; } + /** @type {any[]} */ const uploaded = []; const transaction = { pointerPublished: false }; try { @@ -380,12 +465,15 @@ export async function publishTrunk( options ) { transaction ); } catch ( error ) { - if ( ! transaction.pointerPublished && ! error.pointerStateUnknown ) { + if ( + ! transaction.pointerPublished && + ! errorFlag( error, 'pointerStateUnknown' ) + ) { await cleanupUploaded( session, uploaded ); } if ( error instanceof SupersededTrunkRun || - error.trunkRunSuperseded === true + errorFlag( error, 'trunkRunSuperseded' ) ) { return { status: 'superseded' }; } @@ -393,10 +481,16 @@ export async function publishTrunk( options ) { } } +/** + * @param {Record} result + * @param {string | undefined} enforcementVariable + * @param {(message: string) => unknown} annotate + */ export function enforceTrunkValidationResult( result, enforcementVariable, - annotate = ( message ) => process.stdout.write( `${ message }\n` ) + annotate = /** @param {string} message */ ( message ) => + process.stdout.write( `${ message }\n` ) ) { if ( result.status !== 'invalid' ) { return result; @@ -413,7 +507,11 @@ export function enforceTrunkValidationResult( } async function main() { - const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const eventPath = process.env.GITHUB_EVENT_PATH; + if ( ! eventPath ) { + throw new Error( 'GITHUB_EVENT_PATH is required.' ); + } + const event = JSON.parse( await readFile( eventPath, 'utf8' ) ); const result = enforceTrunkValidationResult( await publishTrunk( { repository: process.env.GITHUB_REPOSITORY, diff --git a/.github/scripts/docs-playground-preview/publish.mjs b/.github/scripts/docs-playground-preview/publish.mjs index c671bea3e9f75..1a9a9233d3ce2 100644 --- a/.github/scripts/docs-playground-preview/publish.mjs +++ b/.github/scripts/docs-playground-preview/publish.mjs @@ -19,8 +19,31 @@ import { findPreviousPreview, loadPublishedPreview } from './lib/published.mjs'; class SupersededRun extends Error {} +/** + * @param {unknown} error + */ +function errorMessage( error ) { + return error instanceof Error ? error.message : String( error ); +} + +/** + * @param {unknown} error + * @param {string} property + */ +function errorFlag( error, property ) { + return ( + error instanceof Error && + /** @type {any} */ ( error )[ property ] === true + ); +} + +/** + * @param {unknown} error + * @returns {string} + */ export function formatFailure( error ) { - const description = error.stack || String( error ); + const description = + error instanceof Error && error.stack ? error.stack : String( error ); if ( ! ( error instanceof AggregateError ) ) { return description; } @@ -33,12 +56,18 @@ export function formatFailure( error ) { ].join( '\n' ); } +/** + * @param {string} directory + */ async function readHandoff( directory ) { return JSON.parse( await readFile( path.join( directory, 'build.json' ), 'utf8' ) ); } +/** + * @param {Record} options + */ async function establishSession( options ) { const api = options.api || @@ -55,7 +84,7 @@ async function establishSession( options ) { if ( run.head_repository?.owner?.login && run.head_branch ) { throw error; } - throw new SupersededRun( error.message ); + throw new SupersededRun( errorMessage( error ) ); } if ( ! pullRequest ) { return null; @@ -72,16 +101,18 @@ async function establishSession( options ) { try { context = validatePublicationContext( base ); } catch ( error ) { - throw new SupersededRun( error.message ); + throw new SupersededRun( errorMessage( error ) ); } + /** @type {(message: string) => unknown} */ + const warning = + options.warning || + ( ( message ) => process.stderr.write( `${ message }\n` ) ); return { api, context, repository: options.repository, fetchImplementation: options.fetchImplementation || globalThis.fetch, - warning: - options.warning || - ( ( message ) => process.stderr.write( `${ message }\n` ) ), + warning, now: options.now || ( () => new Date().toISOString() ), handoffDirectory: path.resolve( options.handoffDirectory ), authorize: async () => { @@ -98,12 +129,15 @@ async function establishSession( options ) { latestRun, } ); } catch ( error ) { - throw new SupersededRun( error.message ); + throw new SupersededRun( errorMessage( error ) ); } }, }; } +/** + * @param {Record} session + */ async function ensureRelease( session ) { let release = await session.api.getRelease(); if ( release ) { @@ -121,6 +155,10 @@ async function ensureRelease( session ) { return release; } +/** + * @param {Record} session + * @param {string} body + */ async function upsertComment( session, body ) { const comment = await session.api.findPreviewComment( session.context.pullRequestNumber @@ -131,22 +169,39 @@ async function upsertComment( session, body ) { await session.api.updateComment( comment.id, body ); return; } catch ( error ) { - if ( error.status !== 404 ) { + if ( + ! errorFlag( error, 'status' ) && + ! ( + error instanceof Error && + 'status' in error && + error.status === 404 + ) + ) { throw error; } session.warning( - `Cannot update the deleted preview comment: ${ error.message }` + `Cannot update the deleted preview comment: ${ errorMessage( + error + ) }` ); } } await session.api.createComment( session.context.pullRequestNumber, body ); } +/** + * @param {Record} session + */ async function removeRequestLabel( session ) { await session.authorize(); await session.api.removeLabel( session.context.pullRequestNumber ); } +/** + * @param {Record} session + * @param {any[]} assets + * @param {Set} keep + */ async function cleanupOldAssets( session, assets, keep ) { const prefix = `code-reference-pr-${ session.context.pullRequestNumber }-`; for ( const asset of assets ) { @@ -157,6 +212,10 @@ async function cleanupOldAssets( session, assets, keep ) { } } +/** + * @param {Record} session + * @param {any[]} assets + */ async function cleanupFailedCandidate( session, assets ) { for ( const asset of assets ) { await session.authorize(); @@ -164,6 +223,10 @@ async function cleanupFailedCandidate( session, assets ) { } } +/** + * @param {any[]} operations + * @param {string} message + */ async function runIndependently( operations, message ) { const errors = []; for ( const operation of operations ) { @@ -185,6 +248,9 @@ async function runIndependently( operations, message ) { } } +/** + * @param {Record} session + */ async function reportFailure( session, excluded = new Set() ) { let previous = await findPreviousPreview( session, excluded ); if ( ! previous ) { @@ -210,6 +276,11 @@ async function reportFailure( session, excluded = new Set() ) { ); } +/** + * @param {Record} session + * @param {any[]} assets + * @param {Set} keep + */ async function finishReady( session, assets, keep ) { try { await runIndependently( @@ -220,11 +291,18 @@ async function finishReady( session, assets, keep ) { 'Old-asset cleanup and label removal both failed.' ); } catch ( error ) { - error.preserveReadyComment = true; - throw error; + throw Object.assign( + error instanceof Error ? error : new Error( String( error ) ), + { preserveReadyComment: true } + ); } } +/** + * @param {Record} session + * @param {Record} metadata + * @param {any[]} uploadedAssets + */ async function publishCandidate( session, metadata, uploadedAssets ) { const candidateFile = path.join( session.handoffDirectory, @@ -282,6 +360,10 @@ async function publishCandidate( session, metadata, uploadedAssets ) { return { status: 'ready', preview }; } +/** + * @param {Record} session + * @param {Record} metadata + */ async function reuseCandidate( session, metadata ) { const release = await session.api.getRelease(); if ( ! release ) { @@ -289,9 +371,15 @@ async function reuseCandidate( session, metadata ) { } const assets = await session.api.listReleaseAssets( release.id ); const snapshotAsset = assets.find( + /** + * @param {Record} asset + */ ( asset ) => asset.name === metadata.reusedSnapshot.assetName ); const metadataAsset = assets.find( + /** + * @param {Record} asset + */ ( asset ) => asset.name === metadata.reusedSnapshot.metadataAssetName ); if ( ! snapshotAsset || ! metadataAsset ) { @@ -337,6 +425,9 @@ async function reuseCandidate( session, metadata ) { return { status: 'reused', preview }; } +/** + * @param {Record} options + */ export async function publishPullRequest( options ) { let session; try { @@ -353,6 +444,7 @@ export async function publishPullRequest( options ) { if ( await session.api.isSkippedPreviewBuild( session.context.run ) ) { return { status: 'ignored' }; } + /** @type {any[]} */ const uploadedAssets = []; try { await session.authorize(); @@ -379,7 +471,7 @@ export async function publishPullRequest( options ) { if ( error instanceof SupersededRun ) { return { status: 'superseded' }; } - if ( error.preserveReadyComment ) { + if ( errorFlag( error, 'preserveReadyComment' ) ) { throw error; } const excluded = new Set( @@ -389,7 +481,9 @@ export async function publishPullRequest( options ) { await cleanupFailedCandidate( session, uploadedAssets ); } catch ( cleanupError ) { session.warning( - `Cannot remove failed candidate: ${ cleanupError.message }` + `Cannot remove failed candidate: ${ errorMessage( + cleanupError + ) }` ); } try { @@ -407,6 +501,10 @@ export async function publishPullRequest( options ) { } } +/** + * @param {Record} result + * @param {string | undefined} enforcementVariable + */ export function enforceValidationResult( result, enforcementVariable ) { if ( result.status === 'invalid' && enforcementVariable === 'true' ) { throw new Error( @@ -417,7 +515,11 @@ export function enforceValidationResult( result, enforcementVariable ) { } async function main() { - const event = JSON.parse( await readFile( process.env.GITHUB_EVENT_PATH ) ); + const eventPath = process.env.GITHUB_EVENT_PATH; + if ( ! eventPath ) { + throw new Error( 'GITHUB_EVENT_PATH is required.' ); + } + const event = JSON.parse( await readFile( eventPath, 'utf8' ) ); const result = enforceValidationResult( await publishPullRequest( { repository: process.env.GITHUB_REPOSITORY, diff --git a/.github/scripts/docs-playground-preview/reuse.mjs b/.github/scripts/docs-playground-preview/reuse.mjs index 05ebe2d952f7d..9f09fcd27bfe4 100644 --- a/.github/scripts/docs-playground-preview/reuse.mjs +++ b/.github/scripts/docs-playground-preview/reuse.mjs @@ -12,7 +12,11 @@ import { validateReusableMetadata, } from './lib/publication.mjs'; +/** + * @param {string[]} values + */ function argumentsFrom( values ) { + /** @type {Record} */ const options = {}; for ( let index = 0; index < values.length; index += 2 ) { const name = values[ index ]; @@ -23,12 +27,23 @@ function argumentsFrom( values ) { options[ name .slice( 2 ) - .replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() ) + .replace( + /-([a-z])/g, + /** @param {string} _ @param {string} letter */ ( + _, + letter + ) => letter.toUpperCase() + ) ] = value; } return options; } +/** + * @param {string} url + * @param {string} token + * @param {(...args: any[]) => any} fetchImplementation + */ async function apiJson( url, token, fetchImplementation ) { const response = await fetchImplementation( url, { headers: { @@ -48,6 +63,12 @@ async function apiJson( url, token, fetchImplementation ) { return response.json(); } +/** + * @param {string} repository + * @param {number} releaseId + * @param {string} token + * @param {(...args: any[]) => any} fetchImplementation + */ async function releaseAssets( repository, releaseId, @@ -68,6 +89,9 @@ async function releaseAssets( } } +/** + * @param {Record} options + */ export async function findReusablePreview( options ) { const fetchImplementation = options.fetchImplementation || globalThis.fetch; const release = await apiJson( @@ -134,7 +158,9 @@ export async function findReusablePreview( options ) { return createReuseHandoff( published, options ); } catch ( error ) { options.warning?.( - `Cannot reuse ${ candidate.name }: ${ error.message }` + `Cannot reuse ${ candidate.name }: ${ + error instanceof Error ? error.message : String( error ) + }` ); } } @@ -147,7 +173,7 @@ async function main() { ...options, maximumBytes: Number( options.maximumBytes ), token: process.env.GITHUB_TOKEN, - warning: ( message ) => + warning: /** @param {string} message */ ( message ) => process.stderr.write( `::warning::${ message }\n` ), } ); if ( handoff ) { diff --git a/.github/scripts/docs-playground-preview/test/base.test.mjs b/.github/scripts/docs-playground-preview/test/base.test.mjs index 2df4dbcbc1132..1da3294dde44a 100644 --- a/.github/scripts/docs-playground-preview/test/base.test.mjs +++ b/.github/scripts/docs-playground-preview/test/base.test.mjs @@ -15,6 +15,9 @@ import { import { zipDirectory } from '../lib/archive.mjs'; import { run } from '../lib/process.mjs'; +/** + * @param {string} cacheDirectory + */ function inputs( cacheDirectory ) { return { cacheKey: 'docs-preview-base-v1-' + 'a'.repeat( 64 ), @@ -42,12 +45,22 @@ function inputs( cacheDirectory ) { }; } +/** + * @param {string | Uint8Array} bytes + */ function sha256( bytes ) { return createHash( 'sha256' ).update( bytes ).digest( 'hex' ); } +/** + * @param {string | Uint8Array} bytes + * @param {Record} downloads + */ function fakeComposerDownload( bytes, downloads ) { - return async ( command, args ) => { + return /** @param {string} command @param {string[]} args */ async ( + command, + args + ) => { downloads.count++; await writeFile( args[ args.indexOf( '--output' ) + 1 ], bytes ); }; @@ -61,14 +74,16 @@ test( 'the invariant Blueprint installs dependencies without importing source', } ); assert.deepEqual( blueprint.features, { networking: false } ); assert.equal( blueprint.login, false ); + /** @type {any[]} */ + const steps = blueprint.steps; assert.equal( - blueprint.steps.some( ( step ) => + steps.some( ( step ) => /import|reference\.json/.test( JSON.stringify( step ) ) ), false ); assert.deepEqual( - blueprint.steps + steps .filter( ( step ) => step.step === 'installTheme' ) .map( ( step ) => step.themeData.path ), [ 'bundles/wporg-parent-2021.zip', 'bundles/wporg-developer-2023.zip' ] @@ -195,21 +210,22 @@ test( 'the invariant base marker is written last and enables exact reuse', async ); const resolved = inputs( path.join( cache, 'entry' ) ); let builds = 0; - const buildImplementation = async ( current ) => { - builds++; - await writeFile( - path.join( current.cacheDirectory, 'base.zip' ), - 'base' - ); - await mkdir( path.join( current.cacheDirectory, 'parser' ) ); - await writeFile( - path.join( - current.cacheDirectory, - 'parser/generate-json-manually.php' - ), - '} current */ async ( current ) => { + builds++; + await writeFile( + path.join( current.cacheDirectory, 'base.zip' ), + 'base' + ); + await mkdir( path.join( current.cacheDirectory, 'parser' ) ); + await writeFile( + path.join( + current.cacheDirectory, + 'parser/generate-json-manually.php' + ), + ' { } ); test( 'the cache cannot claim a toolchain version that did not run', async () => { + /** @type {any[]} */ const commands = []; await verifyToolchain( resolved( '/cache' ), { nodeVersion: '20.20.2', - runImplementation: async ( command ) => { + runImplementation: /** @param {string} command */ async ( command ) => { commands.push( command ); return { stdout: command === 'npm' ? '10.8.2\n' : '8.4' }; }, @@ -142,6 +149,7 @@ test( 'resolve-only records the exact cache inputs without building', async () = path.join( os.tmpdir(), 'docs-preview-resolve-' ) ); const expected = resolved( path.join( root, 'cache/exact' ) ); + /** @type {any} */ let written; const result = await buildCodeReferencePreview( { @@ -155,9 +163,13 @@ test( 'resolve-only records the exact cache inputs without building', async () = { resolveBuildInputs: async () => expected, verifyToolchain: async () => {}, - writeResolvedInputs: async ( inputs, filename ) => { - written = { inputs, filename }; - }, + writeResolvedInputs: + /** @param {Record} inputs @param {string} filename */ async ( + inputs, + filename + ) => { + written = { inputs, filename }; + }, } ); assert.equal( result.inputs, expected ); @@ -168,12 +180,17 @@ test( 'resolve-only records the exact cache inputs without building', async () = ); } ); +/** + * @param {string[]} failures + */ async function fixture( failures = [], enforce = false ) { const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-build-' ) ); const cache = path.join( root, 'cache/exact' ); + /** @type {any[]} */ const calls = []; + /** @type {Record} */ const overrides = { run: async () => {}, verifyToolchain: async () => {}, @@ -182,7 +199,7 @@ async function fixture( failures = [], enforce = false ) { calls.push( 'base' ); return { cacheHit: true }; }, - generateParserJson: async ( options ) => { + generateParserJson: /** @param {Record} options */ async ( options ) => { calls.push( 'parser' ); assert.equal( options.parser, path.join( cache, 'parser' ) ); return parser( failures ); diff --git a/.github/scripts/docs-playground-preview/test/config.test.mjs b/.github/scripts/docs-playground-preview/test/config.test.mjs index 1cbd1f7610f57..19f66212da6bd 100644 --- a/.github/scripts/docs-playground-preview/test/config.test.mjs +++ b/.github/scripts/docs-playground-preview/test/config.test.mjs @@ -182,7 +182,7 @@ test( 'the beta resolver falls back to the latest stable build with a notice', a } ); assert.equal( write.mock.callCount(), 1 ); assert.match( - write.mock.calls[ 0 ].arguments[ 0 ], + String( write.mock.calls[ 0 ].arguments[ 0 ] ), /^::notice::.*tracking the stable release 7\.1\.2 until the next beta appears\./ ); } ); diff --git a/.github/scripts/docs-playground-preview/test/files.test.mjs b/.github/scripts/docs-playground-preview/test/files.test.mjs index e814e9f4c0541..1b7a035bfea93 100644 --- a/.github/scripts/docs-playground-preview/test/files.test.mjs +++ b/.github/scripts/docs-playground-preview/test/files.test.mjs @@ -108,15 +108,23 @@ test( 'acquireRepositories uses Git with each validated full commit', async () = const root = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-repos-' ) ); + /** @type {any[]} */ const calls = []; - const fakeRun = async ( command, args, options ) => { - calls.push( { command, args, options } ); - if ( args[ 0 ] === 'clone' ) { - await mkdir( path.join( args.at( -1 ), '.git' ), { - recursive: true, - } ); - } - }; + const fakeRun = + /** @param {string} command @param {string[]} args @param {Record} [options] */ async ( + command, + args, + options + ) => { + calls.push( { command, args, options } ); + if ( args[ 0 ] === 'clone' ) { + const target = args.at( -1 ); + assert.ok( target ); + await mkdir( path.join( target, '.git' ), { + recursive: true, + } ); + } + }; const repositories = { parser: { repository: 'WordPress/phpdoc-parser', diff --git a/.github/scripts/docs-playground-preview/test/final.test.mjs b/.github/scripts/docs-playground-preview/test/final.test.mjs index c6cead429d0fe..0c64700b2a095 100644 --- a/.github/scripts/docs-playground-preview/test/final.test.mjs +++ b/.github/scripts/docs-playground-preview/test/final.test.mjs @@ -6,6 +6,9 @@ import { test } from 'node:test'; import { createFinalBlueprint, packageFinalSnapshot } from '../lib/final.mjs'; +/** + * @param {string} cacheDirectory + */ function inputs( cacheDirectory, snapshotBytes = 1024 ) { return { cacheDirectory, @@ -26,8 +29,10 @@ test( 'the final Blueprint restores the base before the complete import', () => assert.equal( blueprint.landingPage, '/reference/' ); assert.equal( blueprint.login, false ); assert.deepEqual( blueprint.features, { networking: false } ); + /** @type {any[]} */ + const steps = blueprint.steps; assert.deepEqual( - blueprint.steps.map( ( step ) => step.step ), + steps.map( ( step ) => step.step ), [ 'unzip', 'mkdir', @@ -93,11 +98,16 @@ async function fixture( snapshotBytes = 1024 ) { test( 'final packaging returns publisher metadata for a bounded snapshot', async () => { const current = await fixture(); + /** @type {any} */ let invocation; - const buildSnapshotImplementation = async ( command, options ) => { - invocation = { command, options }; - await writeFile( current.output, 'snapshot' ); - }; + const buildSnapshotImplementation = + /** @param {string} command @param {Record} options */ async ( + command, + options + ) => { + invocation = { command, options }; + await writeFile( current.output, 'snapshot' ); + }; const snapshot = await packageFinalSnapshot( current.resolved, { workDirectory: path.join( current.root, 'work' ), output: current.output, diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index a94a666b91073..d5ab8dda8a254 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -4,12 +4,15 @@ import { test } from 'node:test'; import { GitHubApi } from '../lib/github.mjs'; import { COMMENT_MARKER, RELEASE_TAG } from '../lib/publication.mjs'; +/** + * @param {unknown} value + */ function response( value, status = 200 ) { return { ok: status >= 200 && status < 300, status, json: async () => value, - text: async () => JSON.stringify( value ), + text: async () => JSON.stringify( value ) ?? '', }; } @@ -41,6 +44,7 @@ function pullRequest( overrides = {} ) { } test( 'API requests use the repository token and report failures', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -93,6 +97,7 @@ test( 'a fork run resolves its PR without workflow pull_requests data', async () } ); test( 'latest run lookup binds SHA, branch, repository, and current attempt', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -128,6 +133,7 @@ test( 'latest run lookup binds SHA, branch, repository, and current attempt', as } ); test( 'trunk lookup binds the workflow, branch, repository, and current attempt', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -211,6 +217,7 @@ test( 'skipped trigger runs neither publish nor supersede a build', async () => } ); test( 'release operations keep immutable names and bytes', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -245,6 +252,7 @@ test( 'release operations keep immutable names and bytes', async () => { } ); test( 'a stale duplicate asset is replaced and the upload retried once', async () => { + /** @type {any[]} */ const calls = []; let uploads = 0; const api = new GitHubApi( @@ -330,6 +338,7 @@ test( 'a duplicate asset failure after the retry surfaces as an error', async () } ); test( 'Git object operations create and atomically move a pointer ref', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', @@ -376,6 +385,7 @@ test( 'Git object operations create and atomically move a pointer ref', async () } ); test( 'only the marked bot comment is updated', async () => { + /** @type {any[]} */ const calls = []; const api = new GitHubApi( 'WordPress/wordpress-develop', diff --git a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs index 624e43e7d12b3..cbafcdc23707e 100644 --- a/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs +++ b/.github/scripts/docs-playground-preview/test/lifecycle.test.mjs @@ -21,6 +21,9 @@ const currentSha = 'a'.repeat( 40 ); const previewSha = 'c'.repeat( 40 ); const snapshotBytes = Buffer.from( 'snapshot' ); +/** + * @param {any[]} labels + */ function pullRequest( state = 'open', labels = [], headSha = currentSha ) { return { number: 123, @@ -35,6 +38,9 @@ function pullRequest( state = 'open', labels = [], headSha = currentSha ) { }; } +/** + * @param {string} action + */ function event( action, state = action === 'closed' ? 'closed' : 'open', @@ -43,6 +49,7 @@ function event( return { action, pull_request: pullRequest( state, [], headSha ) }; } +/** @returns {Record} */ function previewMetadata() { const snapshotFilename = snapshotAssetName( { pullRequestNumber: 123, @@ -81,6 +88,10 @@ function previewMetadata() { ); } +/** + * @param {number} id + * @param {string} name + */ function releaseAsset( id, name ) { return { id, @@ -94,18 +105,26 @@ class FakeApi { constructor() { this.currentPullRequest = pullRequest(); this.release = { id: 9 }; + /** @type {any[]} */ this.assets = []; + /** @type {any[]} */ this.caches = []; this.metadata = new Map(); this.assetBytes = new Map(); this.comment = { id: 20, body: `${ COMMENT_MARKER }\nReady` }; + /** @type {any[]} */ this.deletedAssets = []; + /** @type {any[]} */ this.deletedCaches = []; + /** @type {any[]} */ this.commentBodies = []; + /** @type {any} */ this.failedAsset = null; this.cacheRef = null; + /** @type {any} */ this.replacementComment = null; this.commentReads = 0; + /** @type {any} */ this.laterPullRequest = null; this.pullRequestReads = 0; this.reopenAfterAssetDeletion = false; @@ -127,6 +146,9 @@ class FakeApi { return [ ...this.assets ]; } + /** + * @param {string} ref + */ async listActionCaches( ref ) { this.cacheRef = ref; return [ ...this.caches ]; @@ -140,12 +162,19 @@ class FakeApi { return this.comment; } + /** + * @param {number} id + * @param {string} body + */ async updateComment( id, body ) { assert.equal( id, this.comment.id ); this.commentBodies.push( body ); this.comment = { id, body }; } + /** + * @param {number} id + */ async deleteReleaseAsset( id ) { if ( id === this.failedAsset ) { throw new Error( 'release deletion failed' ); @@ -156,11 +185,17 @@ class FakeApi { } } + /** + * @param {number} id + */ async deleteActionCache( id ) { this.deletedCaches.push( id ); } } +/** + * @param {FakeApi} api + */ function installPreview( api ) { const metadata = previewMetadata(); const metadataName = metadataAssetName( metadata.snapshotFilename ); @@ -173,18 +208,25 @@ function installPreview( api ) { return metadata; } +/** + * @param {FakeApi} api + * @returns {(...args: any[]) => Promise} + */ function publicFetch( api ) { - return async ( url ) => { + return /** @param {string} url */ async ( url ) => { if ( url.includes( 'wordpress-playground-cors-proxy.net' ) ) { const name = url.split( '/' ).at( -1 ); return { status: 200, headers: { - get: ( header ) => - ( { + get: /** @param {string} header */ ( header ) => { + /** @type {Record} */ + const values = { 'x-playground-cors-proxy': 'true', 'access-control-allow-origin': PLAYGROUND_ORIGIN, - } )[ header.toLowerCase() ] || null, + }; + return values[ header.toLowerCase() ] || null; + }, }, arrayBuffer: async () => api.assetBytes.get( name ), }; @@ -197,6 +239,10 @@ function publicFetch( api ) { }; } +/** + * @param {FakeApi} api + * @param {Record} lifecycleEvent + */ function options( api, lifecycleEvent ) { return { repository, diff --git a/.github/scripts/docs-playground-preview/test/parser.test.mjs b/.github/scripts/docs-playground-preview/test/parser.test.mjs index 8d4f33e09cb86..0dc69f868f021 100644 --- a/.github/scripts/docs-playground-preview/test/parser.test.mjs +++ b/.github/scripts/docs-playground-preview/test/parser.test.mjs @@ -6,6 +6,7 @@ import { test } from 'node:test'; import { generateParserJson, inspectParserRecords } from '../lib/parser.mjs'; +/** @returns {any[]} */ function records() { return [ { @@ -121,11 +122,16 @@ test( 'generateParserJson stages PHP, invokes the pinned parser, and normalizes await writeFile( path.join( source, 'wp-includes/version.php' ), ' { - invocation = { command, args }; - await writeFile( output, JSON.stringify( records() ) ); - }; + const runImplementation = + /** @param {string} command @param {string[]} args */ async ( + command, + args + ) => { + invocation = { command, args }; + await writeFile( output, JSON.stringify( records() ) ); + }; const result = await generateParserJson( { source: path.dirname( source ), stagedSource: path.join( temporary, 'staged' ), diff --git a/.github/scripts/docs-playground-preview/test/publication.test.mjs b/.github/scripts/docs-playground-preview/test/publication.test.mjs index 0a03d7acea977..6873913261602 100644 --- a/.github/scripts/docs-playground-preview/test/publication.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publication.test.mjs @@ -54,8 +54,14 @@ function published( bytes = Buffer.from( 'snapshot' ) ) { }; } +/** + * @param {Record} values + */ function headers( values ) { - return { get: ( name ) => values[ name.toLowerCase() ] || null }; + return { + get: /** @param {string} name */ ( name ) => + values[ name.toLowerCase() ] || null, + }; } test( 'immutable asset names bind the PR, SHA, run, and attempt', () => { @@ -225,7 +231,7 @@ test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () browser_download_url: 'https://github.com/snapshot.zip', }, ]; - const fetchImplementation = async ( url ) => { + const fetchImplementation = /** @param {string} url */ async ( url ) => { if ( url.includes( '/releases/tags/' ) ) { return { ok: true, status: 200, json: async () => ( { id: 9 } ) }; } @@ -250,6 +256,7 @@ test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () token: 'read-token', fetchImplementation, } ); + assert.ok( handoff ); assert.equal( handoff.handoffType, 'reuse' ); assert.equal( handoff.workflowRunId, identity.workflowRunId ); assert.equal( handoff.reusedSnapshot.assetName, metadata.snapshotFilename ); diff --git a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs index 8e6aa7d856d51..0a52051c012f5 100644 --- a/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish-trunk.test.mjs @@ -39,6 +39,10 @@ function run( overrides = {} ) { }; } +/** + * @param {Record} [overrides] + * @returns {Record} + */ function buildMetadata( overrides = {} ) { const sourceSha = overrides.sourceSha || sha; const workflowRunId = overrides.workflowRunId || '456'; @@ -81,23 +85,32 @@ class FakeApi { this.latestRun = this.currentRun; this.trunkHeadSha = sha; this.release = { id: 9 }; + /** @type {any[]} */ this.assets = []; this.assetBytes = new Map(); + /** @type {any[]} */ this.deleted = []; + /** @type {any[]} */ this.events = []; this.nextId = 10; + /** @type {any} */ this.deleteErrorId = null; this.refSha = null; + /** @type {any} */ this.previousRefSha = null; this.commits = new Map(); this.pendingBlueprint = null; this.refReads = 0; + /** @type {any} */ this.refUpdateFailure = null; this.failRefResolution = false; this.staleRefAfterMutation = false; this.staleContents = false; } + /** + * @param {string} url + */ async request( url ) { assert.equal( url, @@ -141,6 +154,12 @@ class FakeApi { return this.assets.map( ( asset ) => ( { ...asset } ) ); } + /** + * @param {number} releaseId + * @param {string} name + * @param {string | Uint8Array} bytes + * @param {string} contentType + */ async uploadReleaseAsset( releaseId, name, bytes, contentType ) { assert.equal( releaseId, 9 ); const asset = { @@ -155,6 +174,9 @@ class FakeApi { return { ...asset }; } + /** + * @param {string} reference + */ async getGitReference( reference ) { assert.equal( reference, TRUNK_POINTER_REF ); this.refReads++; @@ -169,6 +191,9 @@ class FakeApi { return visibleSha ? { object: { sha: visibleSha } } : null; } + /** + * @param {string} content + */ async createGitBlob( content ) { this.pendingBlueprint = content; this.events.push( 'git:blob' ); @@ -182,17 +207,26 @@ class FakeApi { async createGitCommit() { const commitSha = 'f'.repeat( 40 ); + assert.ok( this.pendingBlueprint ); this.commits.set( commitSha, Buffer.from( this.pendingBlueprint ) ); this.events.push( 'git:commit' ); return { sha: commitSha }; } + /** + * @param {string} reference + * @param {string} candidateSha + */ async createGitReference( reference, candidateSha ) { assert.equal( reference, TRUNK_POINTER_REF ); this.refSha = candidateSha; this.events.push( `git:create-ref:${ candidateSha }` ); } + /** + * @param {string} reference + * @param {string} candidateSha + */ async updateGitReference( reference, candidateSha ) { assert.equal( reference, TRUNK_POINTER_REF ); if ( this.refUpdateFailure === 'before' ) { @@ -205,6 +239,9 @@ class FakeApi { } } + /** + * @param {number} id + */ async deleteReleaseAsset( id ) { if ( id === this.deleteErrorId ) { throw new Error( 'cleanup failed' ); @@ -216,8 +253,13 @@ class FakeApi { } } +/** + * @param {FakeApi} api + * @param {Record} [fetchOptions] + * @returns {(...args: any[]) => Promise} + */ function publicFetch( api, fetchOptions = {} ) { - return async ( url ) => { + return /** @param {string} url */ async ( url ) => { const rawStart = url.indexOf( 'https://raw.githubusercontent.com/' ); if ( rawStart !== -1 ) { const rawUrl = new URL( url.slice( rawStart ) ); @@ -240,11 +282,14 @@ function publicFetch( api, fetchOptions = {} ) { return { status: bytes ? 200 : 404, headers: { - get: ( header ) => - ( { + get: /** @param {string} header */ ( header ) => { + /** @type {Record} */ + const values = { 'x-playground-cors-proxy': 'true', 'access-control-allow-origin': PLAYGROUND_ORIGIN, - } )[ header.toLowerCase() ] || null, + }; + return values[ header.toLowerCase() ] || null; + }, }, arrayBuffer: async () => bytes, }; @@ -260,6 +305,9 @@ function publicFetch( api, fetchOptions = {} ) { .split( '/' ) .at( -1 ); const asset = api.assets.find( + /** + * @param {Record} candidate + */ ( candidate ) => candidate.name === name ); api.events.push( `fetch:${ name }` ); @@ -273,11 +321,14 @@ function publicFetch( api, fetchOptions = {} ) { return { status: 200, headers: { - get: ( header ) => - ( { + get: /** @param {string} header */ ( header ) => { + /** @type {Record} */ + const values = { 'x-playground-cors-proxy': 'true', 'access-control-allow-origin': PLAYGROUND_ORIGIN, - } )[ header.toLowerCase() ] || null, + }; + return values[ header.toLowerCase() ] || null; + }, }, arrayBuffer: async () => bytes, json: async () => JSON.parse( bytes.toString( 'utf8' ) ), @@ -285,6 +336,9 @@ function publicFetch( api, fetchOptions = {} ) { }; } +/** + * @param {Record} metadata + */ async function handoffDirectory( metadata, bytes = snapshotBytes ) { const directory = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-trunk-publish-' ) @@ -302,6 +356,10 @@ async function handoffDirectory( metadata, bytes = snapshotBytes ) { return directory; } +/** + * @param {FakeApi} api + * @param {string} directory + */ function options( api, directory, extra = {} ) { return { repository, @@ -319,6 +377,12 @@ function options( api, directory, extra = {} ) { }; } +/** + * @param {FakeApi} api + * @param {number} id + * @param {string} name + * @param {string | Uint8Array} bytes + */ function addAsset( api, id, name, bytes ) { api.assets.push( { id, @@ -328,6 +392,9 @@ function addAsset( api, id, name, bytes ) { api.assetBytes.set( id, Buffer.from( bytes ) ); } +/** + * @param {FakeApi} api + */ function installPrevious( api ) { const oldSha = 'c'.repeat( 40 ); const oldBytes = Buffer.from( 'old snapshot' ); @@ -364,6 +431,9 @@ function installPrevious( api ) { return { build, published }; } +/** + * @param {FakeApi} api + */ function installOlder( api ) { const olderName = trunkSnapshotAssetName( { sourceSha: '1'.repeat( 40 ), @@ -643,11 +713,13 @@ test( 'a trunk head without a newer build run still publishes with a notice', as const api = new FakeApi(); installPrevious( api ); api.trunkHeadSha = 'b'.repeat( 40 ); + /** @type {any[]} */ const notices = []; const directory = await handoffDirectory( buildMetadata() ); const result = await publishTrunk( options( api, directory, { - notice: ( message ) => notices.push( message ), + notice: /** @param {string} message */ ( message ) => + notices.push( message ), } ) ); assert.equal( result.status, 'ready' ); @@ -659,8 +731,10 @@ test( 'a trunk head without a newer build run still publishes with a notice', as } ); test( 'trunk validation failures enforce or annotate visibly', () => { + /** @type {any[]} */ const messages = []; - const annotate = ( message ) => messages.push( message ); + const annotate = /** @param {string} message */ ( message ) => + messages.push( message ); assert.equal( enforceTrunkValidationResult( { status: 'ready' }, '', annotate ) .status, diff --git a/.github/scripts/docs-playground-preview/test/publish.test.mjs b/.github/scripts/docs-playground-preview/test/publish.test.mjs index 9f89c96d79e39..b35eea384d53f 100644 --- a/.github/scripts/docs-playground-preview/test/publish.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publish.test.mjs @@ -95,6 +95,10 @@ function buildMetadata( overrides = {} ) { }; } +/** + * @param {number} id + * @param {string} name + */ function releaseAsset( id, name, createdAt = '2026-08-08T13:00:00.000Z' ) { return { id, @@ -106,19 +110,26 @@ function releaseAsset( id, name, createdAt = '2026-08-08T13:00:00.000Z' ) { class FakeApi { constructor() { + /** @type {any} */ this.currentRun = run(); this.currentPullRequest = pullRequest(); this.latestRun = this.currentRun; this.release = { id: 9 }; + /** @type {any[]} */ this.assets = []; this.metadata = new Map(); this.assetBytes = new Map(); + /** @type {any[]} */ this.uploads = []; + /** @type {any[]} */ this.deleted = []; + /** @type {any[]} */ this.comments = []; this.labelRemovals = 0; this.runReads = 0; + /** @type {any} */ this.deleteError = null; + /** @type {any} */ this.uploadError = null; } @@ -156,6 +167,12 @@ class FakeApi { return [ ...this.assets ]; } + /** + * @param {number} releaseId + * @param {string} name + * @param {Uint8Array} bytes + * @param {string} contentType + */ async uploadReleaseAsset( releaseId, name, bytes, contentType ) { assert.equal( releaseId, 9 ); if ( this.uploadError ) { @@ -177,6 +194,9 @@ class FakeApi { return asset; } + /** + * @param {number} id + */ async deleteReleaseAsset( id ) { if ( this.deleteError ) { throw this.deleteError; @@ -188,10 +208,18 @@ class FakeApi { return this.comments[ 0 ] || null; } + /** + * @param {number} number + * @param {string} body + */ async createComment( number, body ) { this.comments = [ { id: 1, number, body } ]; } + /** + * @param {number} id + * @param {string} body + */ async updateComment( id, body ) { this.comments = [ { id, body } ]; } @@ -201,8 +229,11 @@ class FakeApi { } } +/** + * @param {FakeApi} api + */ function publicFetch( api, corrupt = new Set() ) { - return async ( url ) => { + return /** @param {string} url */ async ( url ) => { if ( url.includes( 'wordpress-playground-cors-proxy.net' ) ) { const name = url.split( '/' ).at( -1 ); const bytes = corrupt.has( name ) @@ -211,11 +242,14 @@ function publicFetch( api, corrupt = new Set() ) { return { status: 200, headers: { - get: ( header ) => - ( { + get: /** @param {string} header */ ( header ) => { + /** @type {Record} */ + const values = { 'x-playground-cors-proxy': 'true', 'access-control-allow-origin': PLAYGROUND_ORIGIN, - } )[ header.toLowerCase() ] || null, + }; + return values[ header.toLowerCase() ] || null; + }, }, arrayBuffer: async () => bytes, }; @@ -228,6 +262,9 @@ function publicFetch( api, corrupt = new Set() ) { }; } +/** + * @param {Record} metadata + */ async function handoffDirectory( metadata, includeSnapshot = true ) { const directory = await mkdtemp( path.join( os.tmpdir(), 'docs-preview-publish-' ) @@ -245,6 +282,10 @@ async function handoffDirectory( metadata, includeSnapshot = true ) { return directory; } +/** + * @param {FakeApi} api + * @param {string} directory + */ function options( api, directory, extra = {} ) { return { repository, @@ -261,6 +302,10 @@ function options( api, directory, extra = {} ) { }; } +/** + * @param {FakeApi} api + * @param {Record} build + */ function installPublishedPreview( api, build, @@ -578,10 +623,12 @@ test( 'a preview comment deleted mid-update is recreated', async () => { const api = new FakeApi(); api.comments = [ { id: 7, body: 'about to be deleted' } ]; api.updateComment = async () => { - const error = new Error( - `GitHub API returned HTTP 404 for /repos/${ repository }/issues/comments/7: Not Found` + const error = Object.assign( + new Error( + `GitHub API returned HTTP 404 for /repos/${ repository }/issues/comments/7: Not Found` + ), + { status: 404 } ); - error.status = 404; throw error; }; const directory = await handoffDirectory( buildMetadata() ); diff --git a/.github/scripts/docs-playground-preview/test/published.test.mjs b/.github/scripts/docs-playground-preview/test/published.test.mjs index 2f094e9fcfdd1..2ad73a06f3667 100644 --- a/.github/scripts/docs-playground-preview/test/published.test.mjs +++ b/.github/scripts/docs-playground-preview/test/published.test.mjs @@ -65,6 +65,9 @@ function published() { }; } +/** + * @param {Record} metadata + */ function assets( metadata ) { return { metadataAsset: { @@ -84,17 +87,23 @@ function assets( metadata ) { } function headers() { + /** @type {Record} */ + const values = { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + }; return { - get: ( name ) => - ( { - 'x-playground-cors-proxy': 'true', - 'access-control-allow-origin': PLAYGROUND_ORIGIN, - } )[ name.toLowerCase() ] || null, + get: /** @param {string} name */ ( name ) => + values[ name.toLowerCase() ] || null, }; } +/** + * @param {Record} metadata + * @param {Record} metadataAsset + */ function publicFetch( metadata, metadataAsset ) { - return async ( url ) => { + return /** @param {string} url */ async ( url ) => { if ( url === metadataAsset.browser_download_url ) { return { status: 200, json: async () => metadata }; } @@ -162,7 +171,7 @@ test( 'a published preview rejects invalid pointer identity and proxy bytes', as { sourceRepository, sourceSha, - fetchImplementation: async ( url ) => { + fetchImplementation: /** @param {string} url */ async ( url ) => { if ( url === metadataAsset.browser_download_url ) { return { status: 200, json: async () => metadata }; } @@ -188,12 +197,14 @@ test( 'previous-preview discovery skips broken and excluded assets', async () => browser_download_url: 'https://github.com/metadata/broken.json', created_at: '2026-08-09T12:36:00Z', }; + /** @type {any[]} */ const warnings = []; const session = { repository, context: { pullRequestNumber }, - warning: ( message ) => warnings.push( message ), - fetchImplementation: async ( url ) => { + warning: /** @param {string} message */ ( message ) => + warnings.push( message ), + fetchImplementation: /** @param {string} url */ async ( url ) => { if ( url === broken.browser_download_url ) { return { status: 404 }; } diff --git a/.github/scripts/docs-playground-preview/test/publisher.test.mjs b/.github/scripts/docs-playground-preview/test/publisher.test.mjs index a90dceeeeb5f2..d18292c138ff6 100644 --- a/.github/scripts/docs-playground-preview/test/publisher.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publisher.test.mjs @@ -145,7 +145,8 @@ test( 'latest-wins requires the label except for an explicit rerun', () => { test( 'a fresh candidate must pass every publisher identity field', () => { assert.equal( inspectHandoff( metadata(), context() ).kind, 'candidate' ); - for ( const [ name, value, error ] of [ + /** @type {Array<[string, any, RegExp]>} */ + const invalidFields = [ [ 'schemaVersion', 2, /schema/ ], [ 'sourceSha', 'c'.repeat( 40 ), /workflow run/ ], [ 'workflowRunAttempt', 2, /workflow run/ ], @@ -155,7 +156,8 @@ test( 'a fresh candidate must pass every publisher identity field', () => { [ 'snapshotFilename', 'snapshot.zip', /filename/ ], [ 'snapshotBytes', 104857601, /100 MiB/ ], [ 'snapshotSha256', 'broken', /digest/ ], - ] ) { + ]; + for ( const [ name, value, error ] of invalidFields ) { assert.throws( () => inspectHandoff( metadata( { [ name ]: value } ), context() ), error @@ -267,7 +269,7 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { sourceSha: sha, publication: { playgroundUrl: preview.publication.playgroundUrl }, } ); - assert.equal( ready.match( /Open Code Reference preview/g ).length, 1 ); + assert.equal( ready.match( /Open Code Reference preview/g )?.length, 1 ); const failed = renderPreviewComment( { status: 'failed', @@ -278,7 +280,10 @@ test( 'the sticky comment has ready, failed, stale, and expired states', () => { previous: preview, } ); assert.match( failed, /Latest attempt failed/ ); - assert.equal( failed.match( /Latest successful docs preview/g ).length, 1 ); + assert.equal( + failed.match( /Latest successful docs preview/g )?.length, + 1 + ); assert.deepEqual( readPreviewCommentSuccess( failed ), { sourceRepository: preview.sourceRepository, sourceSha: sha, diff --git a/.github/scripts/docs-playground-preview/test/trunk.test.mjs b/.github/scripts/docs-playground-preview/test/trunk.test.mjs index 0ddafa20cc00e..585065567fbcf 100644 --- a/.github/scripts/docs-playground-preview/test/trunk.test.mjs +++ b/.github/scripts/docs-playground-preview/test/trunk.test.mjs @@ -83,12 +83,16 @@ function metadata( overrides = {} ) { } function headers( overrides = {} ) { + /** @type {Record} */ const values = { 'x-playground-cors-proxy': 'true', 'access-control-allow-origin': PLAYGROUND_ORIGIN, ...overrides, }; - return { get: ( name ) => values[ name.toLowerCase() ] || null }; + return { + get: /** @param {string} name */ ( name ) => + values[ name.toLowerCase() ] || null, + }; } test( 'trunk assets bind the exact SHA, run, and attempt', () => { @@ -184,9 +188,11 @@ test( 'supersession races are marked distinctly from identity failures', () => { validateTrunkPublicationContext( context( { triggerRunAttempt: 1 } ) ), - ( error ) => - error.trunkRunSuperseded === true && - /no longer current/.test( error.message ) + /** @type {(error: any) => boolean} */ ( + ( error ) => + error.trunkRunSuperseded === true && + /no longer current/.test( error.message ) + ) ); assert.throws( () => @@ -194,9 +200,11 @@ test( 'supersession races are marked distinctly from identity failures', () => { ...context(), run: { ...context().run, status: 'in_progress' }, } ), - ( error ) => - error.trunkRunSuperseded === true && - /not terminal/.test( error.message ) + /** @type {(error: any) => boolean} */ ( + ( error ) => + error.trunkRunSuperseded === true && + /not terminal/.test( error.message ) + ) ); assert.throws( () => @@ -204,9 +212,11 @@ test( 'supersession races are marked distinctly from identity failures', () => { ...context(), run: { ...context().run, head_branch: 'main' }, } ), - ( error ) => - error.trunkRunSuperseded === undefined && - /workflow identity/.test( error.message ) + /** @type {(error: any) => boolean} */ ( + ( error ) => + error.trunkRunSuperseded === undefined && + /workflow identity/.test( error.message ) + ) ); assert.throws( () => @@ -214,7 +224,9 @@ test( 'supersession races are marked distinctly from identity failures', () => { ...context(), latestRun: { ...context().run, id: 999 }, } ), - ( error ) => error.trunkRunSuperseded === true + /** @type {(error: any) => boolean} */ ( + ( error ) => error.trunkRunSuperseded === true + ) ); } ); @@ -240,7 +252,8 @@ test( 'the trunk handoff accepts only a passed exact-run candidate', () => { ).kind, 'failed' ); - for ( const [ name, value, error ] of [ + /** @type {Array<[string, any, RegExp]>} */ + const invalidFields = [ [ 'pullRequestNumber', 123, /trunk run/ ], [ 'sourceSha', 'c'.repeat( 40 ), /trunk run/ ], [ 'workflowRunAttempt', 1, /trunk run/ ], @@ -248,7 +261,8 @@ test( 'the trunk handoff accepts only a passed exact-run candidate', () => { [ 'dependencyManifestDigest', 'broken', /dependency identity/ ], [ 'snapshotFilename', 'snapshot.zip', /filename/ ], [ 'snapshotBytes', 104857601, /snapshot identity/ ], - ] ) { + ]; + for ( const [ name, value, error ] of invalidFields ) { assert.throws( () => inspectTrunkHandoff( @@ -297,16 +311,17 @@ test( 'the public Blueprint must arrive intact through the Playground proxy', as ) ); const publicUrl = trunkStableBlueprintUrl( repository ); - const fetchImplementation = async ( url, options ) => { - assert.equal( url, corsProxyUrl( publicUrl ) ); - assert.equal( options.headers.Origin, PLAYGROUND_ORIGIN ); - return { - status: 200, - headers: headers(), - arrayBuffer: async () => - Buffer.from( `${ JSON.stringify( expected ) }\n` ), + const fetchImplementation = + /** @param {string} url @param {Record} options */ async ( url, options ) => { + assert.equal( url, corsProxyUrl( publicUrl ) ); + assert.equal( options.headers.Origin, PLAYGROUND_ORIGIN ); + return { + status: 200, + headers: headers(), + arrayBuffer: async () => + Buffer.from( `${ JSON.stringify( expected ) }\n` ), + }; }; - }; assert.deepEqual( await validatePublicBlueprint( publicUrl, diff --git a/.github/scripts/docs-playground-preview/test/validate.test.mjs b/.github/scripts/docs-playground-preview/test/validate.test.mjs index df3836fd09c3c..122cc6280ee81 100644 --- a/.github/scripts/docs-playground-preview/test/validate.test.mjs +++ b/.github/scripts/docs-playground-preview/test/validate.test.mjs @@ -61,6 +61,9 @@ function inputs() { }; } +/** + * @param {unknown} body + */ function response( body, status = 200, url = 'http://127.0.0.1:9400/' ) { return { status, @@ -70,6 +73,9 @@ function response( body, status = 200, url = 'http://127.0.0.1:9400/' ) { }; } +/** + * @param {string} url + */ function healthyFetch( url ) { if ( url.endsWith( '/wp-json/docs-preview/v1/health' ) ) { return response( @@ -98,6 +104,9 @@ function healthyFetch( url ) { const target = Object.values( inputs().dependencies.validation.routes ).find( ( route ) => url.endsWith( route.path ) ); + if ( ! target ) { + throw new Error( `Unexpected validation URL: ${ url }` ); + } return response( ` ${ target.expectedText }`, 200, @@ -160,7 +169,7 @@ test( 'behavioral validation covers health, routes, search, and banner', async ( test( 'behavioral defects are advisory validation failures', async () => { const result = await inspectSnapshotBehavior( inputs(), { baseUrl: 'http://127.0.0.1:9400', - fetchImplementation: async ( url ) => { + fetchImplementation: /** @param {string} url */ async ( url ) => { if ( url.endsWith( '/health' ) ) { return response( { @@ -216,7 +225,7 @@ test( 'symbol routes may not redirect to a generic successful page', async () => const baseUrl = 'http://127.0.0.1:9400'; const result = await inspectSnapshotBehavior( inputs(), { baseUrl, - fetchImplementation: async ( url ) => { + fetchImplementation: /** @param {string} url */ async ( url ) => { const current = await healthyFetch( url ); if ( url.includes( '/reference/classes/example/' ) ) { return { ...current, url: `${ baseUrl }/reference/` }; From b13236b84de1609d9ec210003ee070c7613cf5ad Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 15:28:00 +0400 Subject: [PATCH 54/59] Ignore *.tsbuildinfo anywhere --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 98bd3613b9f5a..a5a6f7e211522 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ wp-tests-config.php /tests/phpunit/build /wp-cli.local.yml /phpstan.neon -/*.tsbuildinfo +*.tsbuildinfo /jsdoc /composer.lock /vendor From ba80eed23962f8247f6489e8cf4160a47a29ff1a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 15:35:09 +0400 Subject: [PATCH 55/59] Build/Test Tools: Stop scanning the whole trunk build history Every trunk authorization looks up the newest trunk build, and that lookup collects every page of the workflow's run history before selecting one run. The publisher authorizes before each of roughly nine mutations, so the request cost per publication grows with the age of the repository and eats into a token budget shared with the pull request publishers and the lifecycle jobs. Walk the pages lazily and stop at the first page holding a match, which the newest-first ordering makes the newest run. A history with no matching run on early pages still pages through to the end. --- .../docs-playground-preview/lib/github.mjs | 49 ++++++++----- .../test/github.test.mjs | 72 +++++++++++++++++++ 2 files changed, 105 insertions(+), 16 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index 87d2382fc8762..71ff155ab18cf 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -76,22 +76,34 @@ export class GitHubApi { /** * @param {string} path * @param {string | null} [field] + * @returns {AsyncGenerator} */ - async pages( path, field = null ) { - const values = []; + async *pageBatches( path, field = null ) { for ( let page = 1; ; page++ ) { const separator = path.includes( '?' ) ? '&' : '?'; const response = await this.request( `${ path }${ separator }per_page=100&page=${ page }` ); const batch = field ? response[ field ] : response; - values.push( ...batch ); + yield batch; if ( batch.length < 100 ) { - return values; + return; } } } + /** + * @param {string} path + * @param {string | null} [field] + */ + async pages( path, field = null ) { + const values = []; + for await ( const batch of this.pageBatches( path, field ) ) { + values.push( ...batch ); + } + return values; + } + /** * @param {number} runId */ @@ -190,7 +202,10 @@ export class GitHubApi { } async latestTrunkPreviewRun() { - const runs = await this.pages( + // Every authorization repeats this lookup, and the API answers newest + // first, so the first page holding a match ends the scan instead of + // walking the entire trunk build history. + const batches = this.pageBatches( `/repos/${ this.repository }/actions/workflows/${ BUILD_WORKFLOW }/runs?${ query( { @@ -199,18 +214,20 @@ export class GitHubApi { } ) }`, 'workflow_runs' ); - const latest = runs - .filter( - ( run ) => - run.event === 'push' && - run.head_branch === 'trunk' && - run.head_repository?.full_name === this.repository - ) - .sort( ( left, right ) => right.id - left.id )[ 0 ]; - if ( ! latest ) { - throw new Error( 'No current trunk docs preview build exists.' ); + for await ( const batch of batches ) { + const latest = batch + .filter( + ( run ) => + run.event === 'push' && + run.head_branch === 'trunk' && + run.head_repository?.full_name === this.repository + ) + .sort( ( left, right ) => right.id - left.id )[ 0 ]; + if ( latest ) { + return this.getRun( latest.id ); + } } - return this.getRun( latest.id ); + throw new Error( 'No current trunk docs preview build exists.' ); } /** diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index d5ab8dda8a254..d6c7dca6e7fcb 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -185,6 +185,78 @@ test( 'trunk lookup binds the workflow, branch, repository, and current attempt' assert.match( calls[ 2 ], /actions\/runs\/456$/ ); } ); +test( 'the trunk build lookup stops at the first page holding a match', async () => { + /** @type {any[]} */ + const requested = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + if ( url.includes( '/actions/workflows/' ) ) { + requested.push( url ); + return response( { + workflow_runs: Array.from( { length: 100 }, ( _, index ) => + run( { + id: 1000 - index, + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'WordPress/wordpress-develop', + }, + } ) + ), + } ); + } + return response( run( { id: 1000 } ) ); + } + ); + assert.equal( ( await api.latestTrunkPreviewRun() ).id, 1000 ); + assert.equal( requested.length, 1 ); + assert.match( requested[ 0 ], /page=1$/ ); +} ); + +test( 'the trunk build lookup pages past unrelated runs', async () => { + /** @type {any[]} */ + const requested = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url ) => { + if ( ! url.includes( '/actions/workflows/' ) ) { + return response( run( { id: 321 } ) ); + } + requested.push( url ); + if ( url.endsWith( 'page=1' ) ) { + return response( { + workflow_runs: Array.from( { length: 100 }, () => + run( { + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'other/wordpress-develop', + }, + } ) + ), + } ); + } + return response( { + workflow_runs: [ + run( { + id: 321, + event: 'push', + head_branch: 'trunk', + head_repository: { + full_name: 'WordPress/wordpress-develop', + }, + } ), + ], + } ); + } + ); + assert.equal( ( await api.latestTrunkPreviewRun() ).id, 321 ); + assert.equal( requested.length, 2 ); +} ); + test( 'skipped trigger runs neither publish nor supersede a build', async () => { const api = new GitHubApi( 'WordPress/wordpress-develop', From 28f79c868725e0e1e68344804777515de780c346 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 15:36:18 +0400 Subject: [PATCH 56/59] Build/Test Tools: Skip publishing for skipped builds Every push to an open trunk pull request completes a build run, and unlabeled pull requests skip all of its jobs. The publisher only recognizes that after checking out the repository and installing Node, so each of those pushes spends a runner job to reach a no-op result. Filter the skipped conclusion out of the publish job condition. Failed and cancelled builds still reach the publisher, which reports them on the pull request. --- .github/workflows/docs-playground-preview-publish.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docs-playground-preview-publish.yml b/.github/workflows/docs-playground-preview-publish.yml index 7096a4bf758e1..ee76081605f34 100644 --- a/.github/workflows/docs-playground-preview-publish.yml +++ b/.github/workflows/docs-playground-preview-publish.yml @@ -18,8 +18,12 @@ permissions: {} jobs: publish: name: Publish Code Reference snapshot + # Every push to an unlabeled pull request completes a build run whose + # jobs all skipped. Failed builds still publish their report, so only + # the skipped conclusion is filtered out here. if: >- github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion != 'skipped' && ( github.repository == 'WordPress/wordpress-develop' || ( github.repository == 'sirreal/wordpress-develop' && vars.DOCS_PREVIEW_STAGING == 'true' ) ) runs-on: ubuntu-24.04 From 55dca5c50f14b0b34e5e660f289a764625f08f63 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 15:38:41 +0400 Subject: [PATCH 57/59] Build/Test Tools: Harden preview reuse and output capture Three small defects share a shape: a boundary that fails quietly. Asset pagination spreads the null that a deleted release returns, so the reuse check reports an unrelated type error instead of an absent release. The size boundary reaches the guards as NaN when the argument is missing or malformed, and every guard compares with a greater-than that NaN passes, so the cap silently disappears. Captured output concatenates each pipe chunk as its own string, so a character split across a chunk boundary reaches log files and error text as replacement characters. Treat a missing page as the end of the assets, refuse reuse without a usable size boundary, and decode captured streams as whole text. --- .../docs-playground-preview/lib/process.mjs | 4 +++ .../scripts/docs-playground-preview/reuse.mjs | 15 ++++++++ .../test/process.test.mjs | 18 ++++++++++ .../test/publication.test.mjs | 35 +++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 .github/scripts/docs-playground-preview/test/process.test.mjs diff --git a/.github/scripts/docs-playground-preview/lib/process.mjs b/.github/scripts/docs-playground-preview/lib/process.mjs index aad8f4e8c8747..49a8c32eff4ff 100644 --- a/.github/scripts/docs-playground-preview/lib/process.mjs +++ b/.github/scripts/docs-playground-preview/lib/process.mjs @@ -20,6 +20,10 @@ export async function run( command, args, options = {} ) { } ); let stdout = ''; let stderr = ''; + // Decoding per chunk would corrupt any character split across a pipe + // boundary, so the streams decode as a whole. + child.stdout?.setEncoding( 'utf8' ); + child.stderr?.setEncoding( 'utf8' ); child.stdout?.on( 'data', ( chunk ) => { stdout += chunk; } ); diff --git a/.github/scripts/docs-playground-preview/reuse.mjs b/.github/scripts/docs-playground-preview/reuse.mjs index 9f09fcd27bfe4..c2aa78e63b30b 100644 --- a/.github/scripts/docs-playground-preview/reuse.mjs +++ b/.github/scripts/docs-playground-preview/reuse.mjs @@ -82,6 +82,11 @@ async function releaseAssets( token, fetchImplementation ); + // A release deleted mid-scan reports no assets rather than crashing + // the reuse check with an unrelated error. + if ( ! batch ) { + return assets; + } assets.push( ...batch ); if ( batch.length < 100 ) { return assets; @@ -93,6 +98,16 @@ async function releaseAssets( * @param {Record} options */ export async function findReusablePreview( options ) { + // Every size guard compares with `>`, which a missing or malformed + // boundary would pass as NaN, so reuse is refused instead. + if ( + ! Number.isSafeInteger( options.maximumBytes ) || + options.maximumBytes < 1 + ) { + throw new Error( + 'The maximum snapshot size must be a positive integer.' + ); + } const fetchImplementation = options.fetchImplementation || globalThis.fetch; const release = await apiJson( `https://api.github.com/repos/${ options.repository }/releases/tags/${ RELEASE_TAG }`, diff --git a/.github/scripts/docs-playground-preview/test/process.test.mjs b/.github/scripts/docs-playground-preview/test/process.test.mjs new file mode 100644 index 0000000000000..72ad086920153 --- /dev/null +++ b/.github/scripts/docs-playground-preview/test/process.test.mjs @@ -0,0 +1,18 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; + +import { run } from '../lib/process.mjs'; + +test( 'captured output survives multibyte characters split across chunks', async () => { + // Three bytes per character and far more than one pipe chunk guarantees a + // character straddles a chunk boundary. + const repetitions = 100000; + const result = await run( + process.execPath, + [ '-e', `process.stdout.write( '…'.repeat( ${ repetitions } ) )` ], + { capture: true, quiet: true } + ); + assert.equal( result.code, 0 ); + assert.equal( result.stdout, '…'.repeat( repetitions ) ); + assert.ok( ! result.stdout.includes( '�' ) ); +} ); diff --git a/.github/scripts/docs-playground-preview/test/publication.test.mjs b/.github/scripts/docs-playground-preview/test/publication.test.mjs index 6873913261602..3605934ae75c4 100644 --- a/.github/scripts/docs-playground-preview/test/publication.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publication.test.mjs @@ -266,3 +266,38 @@ test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () handoff.reusedSnapshot ); } ); + +test( 'a release deleted mid-scan ends the reuse check without a crash', async () => { + const fetchImplementation = /** @param {string} url */ async ( url ) => { + if ( url.includes( '/releases/tags/' ) ) { + return { ok: true, status: 200, json: async () => ( { id: 9 } ) }; + } + assert.match( url, /\/releases\/9\/assets/ ); + return { ok: false, status: 404, json: async () => ( {} ) }; + }; + assert.equal( + await findReusablePreview( { + ...identity, + token: 'read-token', + fetchImplementation, + } ), + null + ); +} ); + +test( 'reuse refuses to run without a usable size boundary', async () => { + const fetchImplementation = async () => { + assert.fail( 'No request may be made without a size boundary.' ); + }; + for ( const maximumBytes of [ undefined, NaN, 0, -1, 1.5, '100' ] ) { + await assert.rejects( + findReusablePreview( { + ...identity, + maximumBytes, + token: 'read-token', + fetchImplementation, + } ), + /maximum snapshot size/ + ); + } +} ); From 54debcd0df990bd1adda093b28267f351d14b78d Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 20:14:54 +0400 Subject: [PATCH 58/59] Build/Test Tools: Give every remote read a deadline No request in the preview pipeline carries a timeout. A stalled proxy or API connection therefore runs until the job timeout kills it, which in the ten minute stale job leaves the preview comment advertising a ready preview for an outdated commit, with nothing in the log explaining why. Attach a deadline to every remote call: thirty seconds for API reads and metadata, five minutes for the snapshot transfers that move a hundred megabytes through the proxy. The Playground probes keep their own boot deadline. --- .../docs-playground-preview/lib/config.mjs | 3 ++ .../docs-playground-preview/lib/github.mjs | 6 +++- .../docs-playground-preview/lib/http.mjs | 7 +++++ .../lib/publication.mjs | 3 ++ .../docs-playground-preview/lib/published.mjs | 5 +++- .../docs-playground-preview/lib/trunk.mjs | 2 ++ .../docs-playground-preview/publish-trunk.mjs | 4 ++- .../scripts/docs-playground-preview/reuse.mjs | 5 +++- .../test/github.test.mjs | 2 ++ .../test/publication.test.mjs | 29 +++++++++++++++++++ 10 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 .github/scripts/docs-playground-preview/lib/http.mjs diff --git a/.github/scripts/docs-playground-preview/lib/config.mjs b/.github/scripts/docs-playground-preview/lib/config.mjs index b0f903d4c138f..47f1f9eedf386 100644 --- a/.github/scripts/docs-playground-preview/lib/config.mjs +++ b/.github/scripts/docs-playground-preview/lib/config.mjs @@ -1,6 +1,8 @@ import { createHash } from 'node:crypto'; import { readFile } from 'node:fs/promises'; +import { REQUEST_TIMEOUT_MS } from './http.mjs'; + const FULL_COMMIT = /^[0-9a-f]{40}$/; const FULL_DIGEST = /^[0-9a-f]{64}$/; const VERSION = /^\d+\.\d+\.\d+$/; @@ -168,6 +170,7 @@ export async function resolveWordPressBeta( ) { const response = await fetchImplementation( VERSION_API, { headers: { Accept: 'application/json' }, + signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ), } ); if ( ! response.ok ) { throw new Error( diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index 71ff155ab18cf..6c14f98948618 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -1,3 +1,4 @@ +import { REQUEST_TIMEOUT_MS, TRANSFER_TIMEOUT_MS } from './http.mjs'; import { COMMENT_MARKER, RELEASE_TAG } from './publication.mjs'; const API = 'https://api.github.com'; @@ -35,6 +36,7 @@ export class GitHubApi { * @param {Record} [options] */ async request( url, options = {} ) { + const { timeoutMs = REQUEST_TIMEOUT_MS, ...init } = options; const headers = { Accept: 'application/vnd.github+json', Authorization: `Bearer ${ this.token }`, @@ -44,8 +46,9 @@ export class GitHubApi { const response = await this.fetch( url.startsWith( 'https://' ) ? url : `${ API }${ url }`, { - ...options, + ...init, headers, + signal: AbortSignal.timeout( timeoutMs ), body: options.json === undefined ? options.body @@ -294,6 +297,7 @@ export class GitHubApi { 'Content-Type': contentType, }, body: bytes, + timeoutMs: TRANSFER_TIMEOUT_MS, } ); try { diff --git a/.github/scripts/docs-playground-preview/lib/http.mjs b/.github/scripts/docs-playground-preview/lib/http.mjs new file mode 100644 index 0000000000000..c78f7dc7a25b6 --- /dev/null +++ b/.github/scripts/docs-playground-preview/lib/http.mjs @@ -0,0 +1,7 @@ +// A stalled connection without a deadline runs until the job timeout kills it, +// which leaves a preview reported as still building and no useful log. +export const REQUEST_TIMEOUT_MS = 30_000; + +// Snapshots reach 100 MiB and travel through a third-party proxy, so transfers +// need a deadline far longer than an API call yet shorter than any job. +export const TRANSFER_TIMEOUT_MS = 300_000; diff --git a/.github/scripts/docs-playground-preview/lib/publication.mjs b/.github/scripts/docs-playground-preview/lib/publication.mjs index 0e4c5f5231fdb..9a105fee91c11 100644 --- a/.github/scripts/docs-playground-preview/lib/publication.mjs +++ b/.github/scripts/docs-playground-preview/lib/publication.mjs @@ -1,5 +1,7 @@ import { createHash } from 'node:crypto'; +import { TRANSFER_TIMEOUT_MS } from './http.mjs'; + export const RELEASE_TAG = 'code-reference-playground-preview'; export const COMMENT_MARKER = ''; export const PLAYGROUND_ORIGIN = 'https://playground.wordpress.net'; @@ -168,6 +170,7 @@ export async function validatePublicSnapshot( } const response = await fetchImplementation( corsProxyUrl( publicUrl ), { headers: { Origin: PLAYGROUND_ORIGIN }, + signal: AbortSignal.timeout( TRANSFER_TIMEOUT_MS ), } ); if ( response.status !== 200 ) { throw new Error( diff --git a/.github/scripts/docs-playground-preview/lib/published.mjs b/.github/scripts/docs-playground-preview/lib/published.mjs index cc77e2c69ae88..21440840162b1 100644 --- a/.github/scripts/docs-playground-preview/lib/published.mjs +++ b/.github/scripts/docs-playground-preview/lib/published.mjs @@ -1,3 +1,4 @@ +import { REQUEST_TIMEOUT_MS } from './http.mjs'; import { SNAPSHOT_BYTES_LIMIT } from './publisher.mjs'; import { corsProxyUrl, @@ -16,7 +17,9 @@ const BLUEPRINT_SCHEMA = * @param {(...args: any[]) => any} fetchImplementation */ async function fetchPublishedMetadata( asset, fetchImplementation ) { - const response = await fetchImplementation( asset.browser_download_url ); + const response = await fetchImplementation( asset.browser_download_url, { + signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ), + } ); if ( response.status !== 200 ) { throw new Error( `Public metadata returned HTTP ${ response.status }.` diff --git a/.github/scripts/docs-playground-preview/lib/trunk.mjs b/.github/scripts/docs-playground-preview/lib/trunk.mjs index 4ea55b44c31dc..13980fc66a316 100644 --- a/.github/scripts/docs-playground-preview/lib/trunk.mjs +++ b/.github/scripts/docs-playground-preview/lib/trunk.mjs @@ -1,6 +1,7 @@ import { isDeepStrictEqual } from 'node:util'; import { isDeploymentEnabled } from './config.mjs'; +import { REQUEST_TIMEOUT_MS } from './http.mjs'; import { PLAYGROUND_ORIGIN, SNAPSHOT_BYTES_LIMIT, @@ -333,6 +334,7 @@ export async function readPublicBlueprint( ) { const response = await fetchImplementation( corsProxyUrl( publicUrl ), { headers: { Origin: PLAYGROUND_ORIGIN }, + signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ), } ); if ( response.status !== 200 ) { throw new Error( diff --git a/.github/scripts/docs-playground-preview/publish-trunk.mjs b/.github/scripts/docs-playground-preview/publish-trunk.mjs index 7d343366f37d9..e66a3bc7f7df2 100644 --- a/.github/scripts/docs-playground-preview/publish-trunk.mjs +++ b/.github/scripts/docs-playground-preview/publish-trunk.mjs @@ -6,6 +6,7 @@ import { pathToFileURL } from 'node:url'; import path from 'node:path'; import { GitHubApi } from './lib/github.mjs'; +import { REQUEST_TIMEOUT_MS } from './lib/http.mjs'; import { metadataAssetName, releaseAssetUrl, @@ -148,7 +149,8 @@ async function ensureRelease( session ) { */ async function validatePublicMetadata( session, asset, expected ) { const response = await session.fetchImplementation( - asset.browser_download_url + asset.browser_download_url, + { signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ) } ); if ( response.status !== 200 ) { throw new Error( diff --git a/.github/scripts/docs-playground-preview/reuse.mjs b/.github/scripts/docs-playground-preview/reuse.mjs index c2aa78e63b30b..3a0f4270524ab 100644 --- a/.github/scripts/docs-playground-preview/reuse.mjs +++ b/.github/scripts/docs-playground-preview/reuse.mjs @@ -4,6 +4,7 @@ import { mkdir, writeFile } from 'node:fs/promises'; import { pathToFileURL } from 'node:url'; import path from 'node:path'; +import { REQUEST_TIMEOUT_MS } from './lib/http.mjs'; import { RELEASE_TAG, createReuseHandoff, @@ -51,6 +52,7 @@ async function apiJson( url, token, fetchImplementation ) { Authorization: `Bearer ${ token }`, 'X-GitHub-Api-Version': '2022-11-28', }, + signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ), } ); if ( response.status === 404 ) { return null; @@ -136,7 +138,8 @@ export async function findReusablePreview( options ) { for ( const candidate of candidates ) { try { const metadataResponse = await fetchImplementation( - candidate.browser_download_url + candidate.browser_download_url, + { signal: AbortSignal.timeout( REQUEST_TIMEOUT_MS ) } ); if ( metadataResponse.status !== 200 ) { throw new Error( diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index d6c7dca6e7fcb..0c945575d8749 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -57,6 +57,8 @@ test( 'API requests use the repository token and report failures', async () => { assert.equal( ( await api.getRun( 456 ) ).id, 456 ); assert.match( calls[ 0 ].url, /actions\/runs\/456$/ ); assert.equal( calls[ 0 ].options.headers.Authorization, 'Bearer token' ); + assert.ok( calls[ 0 ].options.signal instanceof AbortSignal ); + assert.equal( calls[ 0 ].options.signal.aborted, false ); const failing = new GitHubApi( 'WordPress/wordpress-develop', diff --git a/.github/scripts/docs-playground-preview/test/publication.test.mjs b/.github/scripts/docs-playground-preview/test/publication.test.mjs index 3605934ae75c4..919602beceed0 100644 --- a/.github/scripts/docs-playground-preview/test/publication.test.mjs +++ b/.github/scripts/docs-playground-preview/test/publication.test.mjs @@ -267,6 +267,35 @@ test( 'same-SHA discovery verifies metadata and the proxied snapshot', async () ); } ); +test( 'the proxied snapshot read carries a deadline', async () => { + const bytes = Buffer.from( 'snapshot' ); + const expected = published( bytes ); + /** @type {any} */ + let signal; + await validatePublicSnapshot( + releaseAssetUrl( identity.repository, expected.snapshotFilename ), + { + bytes: expected.snapshotBytes, + sha256: expected.snapshotSha256, + maximumBytes: identity.maximumBytes, + }, + /** @param {string} _url @param {any} options */ + async ( _url, options ) => { + signal = options.signal; + return { + status: 200, + headers: headers( { + 'x-playground-cors-proxy': 'true', + 'access-control-allow-origin': PLAYGROUND_ORIGIN, + } ), + arrayBuffer: async () => bytes, + }; + } + ); + assert.ok( signal instanceof AbortSignal ); + assert.equal( signal.aborted, false ); +} ); + test( 'a release deleted mid-scan ends the reuse check without a crash', async () => { const fetchImplementation = /** @param {string} url */ async ( url ) => { if ( url.includes( '/releases/tags/' ) ) { From bf332e7d529ca02a8cce0b6620b04802bc980388 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 10 Aug 2026 20:17:10 +0400 Subject: [PATCH 59/59] Build/Test Tools: Retry transient API reads A single transient failure aborts a publication partway through its sequence, because no API call is ever attempted twice. Rate limiting and brief server errors are routine on a shared token, and the publisher issues many reads per publication, so an outage lasting seconds can strand uploaded assets and report a healthy build as broken. Repeat a failed read up to three times, waiting one to two seconds and then two to three, the jitter keeping concurrent jobs from returning together. Mutations are never repeated, since the server may have applied the attempt that appeared to fail. --- .../docs-playground-preview/lib/github.mjs | 93 +++++++++++++------ .../test/github.test.mjs | 48 ++++++++++ 2 files changed, 112 insertions(+), 29 deletions(-) diff --git a/.github/scripts/docs-playground-preview/lib/github.mjs b/.github/scripts/docs-playground-preview/lib/github.mjs index 6c14f98948618..fd29092302600 100644 --- a/.github/scripts/docs-playground-preview/lib/github.mjs +++ b/.github/scripts/docs-playground-preview/lib/github.mjs @@ -3,6 +3,8 @@ import { COMMENT_MARKER, RELEASE_TAG } from './publication.mjs'; const API = 'https://api.github.com'; const UPLOADS = 'https://uploads.github.com'; +const RETRY_ATTEMPTS = 3; +const RETRY_BASE_MS = 1000; const BUILD_WORKFLOW = 'docs-playground-preview-build.yml'; const BUILD_JOB = 'Build Code Reference snapshot'; @@ -43,37 +45,70 @@ export class GitHubApi { 'X-GitHub-Api-Version': '2022-11-28', ...options.headers, }; - const response = await this.fetch( - url.startsWith( 'https://' ) ? url : `${ API }${ url }`, - { - ...init, - headers, - signal: AbortSignal.timeout( timeoutMs ), - body: - options.json === undefined - ? options.body - : JSON.stringify( options.json ), + const target = url.startsWith( 'https://' ) ? url : `${ API }${ url }`; + // Only reads repeat. Repeating a mutation could post a second comment + // or a second upload for an attempt the server had already applied. + const repeatable = ! init.method || init.method === 'GET'; + for ( let attempt = 1; ; attempt++ ) { + const retrying = repeatable && attempt < RETRY_ATTEMPTS; + let response; + try { + response = await this.fetch( target, { + ...init, + headers, + signal: AbortSignal.timeout( timeoutMs ), + body: + options.json === undefined + ? options.body + : JSON.stringify( options.json ), + } ); + } catch ( error ) { + if ( ! retrying ) { + throw error; + } + await this.backoff( attempt ); + continue; } - ); - if ( options.allowNotFound && response.status === 404 ) { - return null; - } - if ( ! response.ok ) { - const detail = await response.text(); - const error = Object.assign( - new Error( - `GitHub API returned HTTP ${ - response.status - } for ${ url }: ${ detail.slice( 0, 300 ) }` - ), - { status: response.status } - ); - throw error; - } - if ( response.status === 204 ) { - return null; + if ( options.allowNotFound && response.status === 404 ) { + return null; + } + if ( ! response.ok ) { + if ( + retrying && + ( response.status === 429 || response.status >= 500 ) + ) { + await this.backoff( attempt ); + continue; + } + const detail = await response.text(); + const error = Object.assign( + new Error( + `GitHub API returned HTTP ${ + response.status + } for ${ url }: ${ detail.slice( 0, 300 ) }` + ), + { status: response.status } + ); + throw error; + } + if ( response.status === 204 ) { + return null; + } + return response.json(); } - return response.json(); + } + + /** + * Spreads repeated attempts so that concurrent jobs meeting the same + * outage do not return in lockstep. + * + * @param {number} attempt + */ + async backoff( attempt ) { + const delay = + RETRY_BASE_MS * 2 ** ( attempt - 1 ) + + Math.random() * RETRY_BASE_MS; + await new Promise( ( resolve ) => setTimeout( resolve, delay ) ); } /** diff --git a/.github/scripts/docs-playground-preview/test/github.test.mjs b/.github/scripts/docs-playground-preview/test/github.test.mjs index 0c945575d8749..37003f3f3394f 100644 --- a/.github/scripts/docs-playground-preview/test/github.test.mjs +++ b/.github/scripts/docs-playground-preview/test/github.test.mjs @@ -68,6 +68,54 @@ test( 'API requests use the repository token and report failures', async () => { await assert.rejects( failing.getRun( 456 ), /HTTP 403/ ); } ); +test( 'transient read failures are retried and mutations are not', async () => { + /** @type {any[]} */ + const attempts = []; + const api = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + attempts.push( options.method || 'GET' ); + if ( attempts.length === 1 ) { + throw new Error( 'socket hang up' ); + } + if ( attempts.length === 2 ) { + return response( { message: 'busy' }, 503 ); + } + return response( { id: 456 } ); + } + ); + api.backoff = async () => {}; + assert.equal( ( await api.getRun( 456 ) ).id, 456 ); + assert.deepEqual( attempts, [ 'GET', 'GET', 'GET' ] ); + + const exhausted = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async () => response( { message: 'busy' }, 503 ) + ); + let reads = 0; + exhausted.backoff = async () => { + reads++; + }; + await assert.rejects( exhausted.getRun( 456 ), /HTTP 503/ ); + assert.equal( reads, 2 ); + + /** @type {any[]} */ + const mutations = []; + const mutating = new GitHubApi( + 'WordPress/wordpress-develop', + 'token', + async ( url, options ) => { + mutations.push( options.method ); + return response( { message: 'busy' }, 503 ); + } + ); + mutating.backoff = async () => assert.fail( 'A mutation must not repeat.' ); + await assert.rejects( mutating.createComment( 123, 'body' ), /HTTP 503/ ); + assert.deepEqual( mutations, [ 'POST' ] ); +} ); + test( 'a fork run resolves its PR without workflow pull_requests data', async () => { const api = new GitHubApi( 'WordPress/wordpress-develop',