diff --git a/Dockerfile.runtime b/Dockerfile.runtime index 95819e284..bf2275985 100644 --- a/Dockerfile.runtime +++ b/Dockerfile.runtime @@ -11,6 +11,7 @@ COPY legal ./legal COPY docs/release/distribution-policy.json ./docs/release/distribution-policy.json COPY packages ./packages COPY scripts ./scripts +COPY vendor ./vendor RUN npm ci --ignore-scripts RUN npm run hydrate:model-data && npm run build:offline diff --git a/package-lock.json b/package-lock.json index 246380bb5..f4a1e1f79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@biomejs/biome": "2.3.5", "@types/node": "22.19.19", "@typescript/native-preview": "7.0.0-dev.20260120.1", + "braces": "file:vendor/braces", "esbuild": "0.28.1", "husky": "9.1.7", "jiti": "2.7.0", @@ -2497,14 +2498,14 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.9.tgz", - "integrity": "sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz", + "integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.9", + "@vitest/utils": "4.1.11", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -2518,8 +2519,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.9", - "vitest": "4.1.9" + "@vitest/browser": "4.1.11", + "vitest": "4.1.11" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2528,16 +2529,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.9.tgz", - "integrity": "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.9", - "@vitest/utils": "4.1.9", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -2546,13 +2547,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.9.tgz", - "integrity": "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.9", + "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -2573,9 +2574,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.9.tgz", - "integrity": "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -2586,13 +2587,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.9.tgz", - "integrity": "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.9", + "@vitest/utils": "4.1.11", "pathe": "^2.0.3" }, "funding": { @@ -2600,14 +2601,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.9.tgz", - "integrity": "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.9", - "@vitest/utils": "4.1.9", + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2616,9 +2617,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.9.tgz", - "integrity": "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", "dev": true, "license": "MIT", "funding": { @@ -2626,13 +2627,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.9.tgz", - "integrity": "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.9", + "@vitest/pretty-format": "4.1.11", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -2735,9 +2736,9 @@ "license": "MIT" }, "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==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -2747,17 +2748,8 @@ } }, "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } + "resolved": "vendor/braces", + "link": true }, "node_modules/buffer": { "version": "5.7.1", @@ -5137,9 +5129,9 @@ } }, "node_modules/undici": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", - "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", + "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", "license": "MIT", "engines": { "node": ">=22.19.0" @@ -5250,19 +5242,19 @@ } }, "node_modules/vitest": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.9.tgz", - "integrity": "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.9", - "@vitest/mocker": "4.1.9", - "@vitest/pretty-format": "4.1.9", - "@vitest/runner": "4.1.9", - "@vitest/snapshot": "4.1.9", - "@vitest/spy": "4.1.9", - "@vitest/utils": "4.1.9", + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -5290,12 +5282,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.9", - "@vitest/browser-preview": "4.1.9", - "@vitest/browser-webdriverio": "4.1.9", - "@vitest/coverage-istanbul": "4.1.9", - "@vitest/coverage-v8": "4.1.9", - "@vitest/ui": "4.1.9", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -5511,9 +5503,9 @@ }, "devDependencies": { "@types/node": "24.12.4", - "@vitest/coverage-v8": "4.1.9", + "@vitest/coverage-v8": "4.1.11", "typescript": "5.9.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5560,7 +5552,7 @@ "devDependencies": { "@types/node": "24.12.4", "canvas": "3.2.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5592,7 +5584,7 @@ }, "devDependencies": { "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5624,7 +5616,7 @@ "proper-lockfile": "4.1.2", "semver": "7.8.0", "typebox": "1.3.7", - "undici": "8.9.0", + "undici": "8.10.2", "yaml": "2.9.0" }, "bin": { @@ -5640,7 +5632,7 @@ "@types/semver": "7.7.1", "shx": "0.4.0", "typescript": "5.9.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5664,7 +5656,7 @@ "devDependencies": { "@diffexai/diffex-client": "^0.3.2", "shx": "0.4.0", - "vitest": "4.1.9", + "vitest": "4.1.11", "ws": "8.21.0" }, "engines": { @@ -5734,7 +5726,7 @@ "@types/node": "24.12.4", "shx": "0.4.0", "typescript": "5.9.3", - "vitest": "4.1.9", + "vitest": "4.1.11", "vitest-evals": "0.15.0" } }, @@ -5769,7 +5761,7 @@ "@types/proper-lockfile": "4.1.4", "shx": "0.4.0", "typebox": "1.3.7", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5804,7 +5796,7 @@ "devDependencies": { "@types/proper-lockfile": "4.1.4", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5820,7 +5812,7 @@ "devDependencies": { "@types/node": "24.12.4", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5852,7 +5844,7 @@ }, "devDependencies": { "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5870,7 +5862,7 @@ "devDependencies": { "@types/ws": "8.18.1", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5885,8 +5877,8 @@ "@diffexai/diffex-ai": "^0.3.2" }, "devDependencies": { - "@vitest/coverage-v8": "4.1.9", - "vitest": "4.1.9" + "@vitest/coverage-v8": "4.1.11", + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5898,7 +5890,7 @@ "license": "Apache-2.0", "devDependencies": { "@types/node": "24.12.4", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "engines": { "node": ">=22.19.0" @@ -5936,6 +5928,15 @@ "engines": { "node": ">=22.19.0" } + }, + "vendor/braces": { + "name": "@diffex-cloud/braces", + "version": "3.0.3-diffex.1", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "7.1.1" + } } } } diff --git a/package.json b/package.json index 70956bcd2..36f6be2c3 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "@biomejs/biome": "2.3.5", "@types/node": "22.19.19", "@typescript/native-preview": "7.0.0-dev.20260120.1", + "braces": "file:vendor/braces", "esbuild": "0.28.1", "husky": "9.1.7", "jiti": "2.7.0", @@ -67,6 +68,7 @@ }, "version": "0.0.3", "overrides": { + "braces": "$braces", "nanoid": "3.3.18", "protobufjs": "7.6.5", "rimraf": "6.1.2", diff --git a/packages/agent/package.json b/packages/agent/package.json index b01023c35..75b2ea540 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -67,9 +67,9 @@ }, "devDependencies": { "@types/node": "24.12.4", - "@vitest/coverage-v8": "4.1.9", + "@vitest/coverage-v8": "4.1.11", "typescript": "5.9.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/ai/package.json b/packages/ai/package.json index 824b02078..428430928 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -102,7 +102,7 @@ "devDependencies": { "@types/node": "24.12.4", "canvas": "3.2.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/client/package.json b/packages/client/package.json index 204ff74e5..db72c3d04 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -65,7 +65,7 @@ }, "devDependencies": { "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/coding-agent-server/package.json b/packages/coding-agent-server/package.json index bcb880ea7..737ff2747 100644 --- a/packages/coding-agent-server/package.json +++ b/packages/coding-agent-server/package.json @@ -48,7 +48,7 @@ "devDependencies": { "@diffexai/diffex-client": "^0.3.2", "shx": "0.4.0", - "vitest": "4.1.9", + "vitest": "4.1.11", "ws": "8.21.0" }, "private": true diff --git a/packages/coding-agent/install-lock/package-lock.json b/packages/coding-agent/install-lock/package-lock.json index e98550e74..6f2ad1b45 100644 --- a/packages/coding-agent/install-lock/package-lock.json +++ b/packages/coding-agent/install-lock/package-lock.json @@ -481,7 +481,7 @@ "proper-lockfile": "4.1.2", "semver": "7.8.0", "typebox": "1.3.7", - "undici": "8.9.0", + "undici": "8.10.2", "yaml": "2.9.0" }, "optionalDependencies": { @@ -1212,9 +1212,9 @@ "license": "MIT" }, "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==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -1912,9 +1912,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", - "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", + "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", "license": "MIT", "engines": { "node": ">=22.19.0" diff --git a/packages/coding-agent/npm-shrinkwrap.json b/packages/coding-agent/npm-shrinkwrap.json index f5563800b..514fbb17e 100644 --- a/packages/coding-agent/npm-shrinkwrap.json +++ b/packages/coding-agent/npm-shrinkwrap.json @@ -36,7 +36,7 @@ "proper-lockfile": "4.1.2", "semver": "7.8.0", "typebox": "1.3.7", - "undici": "8.9.0", + "undici": "8.10.2", "yaml": "2.9.0" }, "optionalDependencies": { @@ -1202,9 +1202,9 @@ "license": "MIT" }, "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==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -1902,9 +1902,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", - "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", + "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", "license": "MIT", "engines": { "node": ">=22.19.0" diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 0725d1283..89f8a5337 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -71,7 +71,7 @@ "proper-lockfile": "4.1.2", "semver": "7.8.0", "typebox": "1.3.7", - "undici": "8.9.0", + "undici": "8.10.2", "yaml": "2.9.0" }, "overrides": { @@ -94,7 +94,7 @@ "@types/semver": "7.7.1", "shx": "0.4.0", "typescript": "5.9.3", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "keywords": [ "coding-agent", diff --git a/packages/evals/package.json b/packages/evals/package.json index 4bd297b17..72e1939d9 100644 --- a/packages/evals/package.json +++ b/packages/evals/package.json @@ -15,6 +15,6 @@ "shx": "0.4.0", "typescript": "5.9.3", "vitest-evals": "0.15.0", - "vitest": "4.1.9" + "vitest": "4.1.11" } } diff --git a/packages/evolution/package.json b/packages/evolution/package.json index ef94a9f80..d9b6d9c70 100644 --- a/packages/evolution/package.json +++ b/packages/evolution/package.json @@ -45,6 +45,6 @@ "@types/proper-lockfile": "4.1.4", "shx": "0.4.0", "typebox": "1.3.7", - "vitest": "4.1.9" + "vitest": "4.1.11" } } diff --git a/packages/harness-state/package.json b/packages/harness-state/package.json index 7b43b476e..fd5141a24 100644 --- a/packages/harness-state/package.json +++ b/packages/harness-state/package.json @@ -50,7 +50,7 @@ "devDependencies": { "@types/proper-lockfile": "4.1.4", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/harness-trace/package.json b/packages/harness-trace/package.json index e1c7998ab..c29bad8c1 100644 --- a/packages/harness-trace/package.json +++ b/packages/harness-trace/package.json @@ -41,6 +41,6 @@ "devDependencies": { "@types/node": "24.12.4", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" } } diff --git a/packages/protocol/package.json b/packages/protocol/package.json index d5e3937a5..ae93d8073 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/server/package.json b/packages/server/package.json index 78ac968a1..c58d66fa6 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@types/ws": "8.18.1", "shx": "0.4.0", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/packages/session-backends/sqlite-node/package.json b/packages/session-backends/sqlite-node/package.json index 7e9e41261..2dff3ca97 100644 --- a/packages/session-backends/sqlite-node/package.json +++ b/packages/session-backends/sqlite-node/package.json @@ -44,8 +44,8 @@ "@diffexai/diffex-agent-core": "^0.3.2" }, "devDependencies": { - "@vitest/coverage-v8": "4.1.9", - "vitest": "4.1.9" + "@vitest/coverage-v8": "4.1.11", + "vitest": "4.1.11" }, "private": true } diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index dfa16b497..23116e8ed 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@types/node": "24.12.4", - "vitest": "4.1.9" + "vitest": "4.1.11" }, "private": true } diff --git a/scripts/vendored-braces-security.test.mjs b/scripts/vendored-braces-security.test.mjs new file mode 100644 index 000000000..7986e0f5e --- /dev/null +++ b/scripts/vendored-braces-security.test.mjs @@ -0,0 +1,162 @@ +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import test from "node:test"; + +const require = createRequire(import.meta.url); +const shxRequire = createRequire(require.resolve("shx/package.json")); +const shellRequire = createRequire(shxRequire.resolve("shelljs")); +const globRequire = createRequire(shellRequire.resolve("fast-glob")); +const matchRequire = createRequire(globRequire.resolve("micromatch")); +const braces = matchRequire("braces"); +const glob = shellRequire("fast-glob"); +const match = globRequire("micromatch"); +const nested = (depth, open = "{", close = "}") => open.repeat(depth) + "x" + close.repeat(depth); + +function directAst(depth) { + let node = { type: "text", value: "x" }; + for (let i = 0; i < depth; i++) { + const parent = { type: "paren", nodes: [node] }; + node.parent = parent; + node = parent; + } + const root = { type: "root", nodes: [node] }; + node.parent = root; + return root; +} + +test("actual shx dependency resolves the transparent private patch", () => { + const manifest = matchRequire("braces/package.json"); + assert.equal(manifest.name, "@diffex-cloud/braces"); + assert.equal(manifest.version, "3.0.3-diffex.1"); +}); + +for (const [open, close] of [ + ["{", "}"], + ["(", ")"], + ["{(", ")}"], +]) { + test(`bounds combined nesting for ${open}`, () => { + const boundary = open.length === 2 ? 50 : 100; + for (const method of ["parse", "compile", "expand", "stringify"]) { + assert.doesNotThrow(() => braces[method](nested(boundary, open, close))); + assert.throws(() => braces[method](nested(boundary + 1, open, close)), /maximum depth/u); + } + assert.throws(() => braces(nested(4000), { maxDepth: Infinity }), /maximum depth/u); + }); +} + +for (const method of ["compile", "expand", "stringify"]) { + test(`protects caller-supplied ASTs in ${method}`, () => { + assert.doesNotThrow(() => braces[method](directAst(100))); + assert.throws(() => braces[method](directAst(4000)), /maximum depth/u); + const cycle = { type: "root", nodes: [] }; + cycle.nodes.push(cycle); + assert.throws(() => braces[method](cycle), /maximum depth/u); + const array = []; + array.push(array); + assert.throws( + () => braces[method]({ type: "root", nodes: [{ type: "text", value: array }] }), + /AST values must be strings/u, + ); + }); +} + +test("bounds cyclic parent traversal and recursive helper arrays", () => { + const parent = { type: "paren", nodes: [] }; + parent.parent = parent; + assert.throws(() => braces.expand(parent), /maximum depth/u); + const utils = createRequire(matchRequire.resolve("braces"))("./lib/utils.js"); + let deep = ["x"]; + for (let i = 0; i < 4000; i++) deep = [deep]; + assert.throws(() => utils.flatten(deep), /maximum depth/u); + const cycle = []; + cycle.push(cycle); + assert.throws(() => utils.flatten(cycle), /maximum depth/u); +}); + +test("validates range AST values before numeric coercion", () => { + let step = ["1"]; + for (let i = 0; i < 4000; i++) step = [step]; + for (const method of ["compile", "expand", "stringify"]) { + const range = { + type: "root", + nodes: [ + { + type: "brace", + nodes: ["1", "2", step].map((value) => ({ type: "text", value })), + open: true, + close: true, + commas: 0, + ranges: 1, + }, + ], + }; + assert.throws(() => braces[method](range), /AST values must be strings/u); + } +}); + +test("preserves alternatives, ranges, escaping, and options", () => { + assert.deepEqual(braces.expand("a/{b,{c,d}}/{01..03..2}"), [ + "a/b/01", + "a/b/03", + "a/c/01", + "a/c/03", + "a/d/01", + "a/d/03", + ]); + assert.deepEqual(braces.expand("{a..e..2}"), ["a", "c", "e"]); + assert.deepEqual(braces.expand("{-2..2}"), ["-2", "-1", "0", "1", "2"]); + assert.deepEqual(braces.expand("{a,b}{c,d}"), ["ac", "ad", "bc", "bd"]); + assert.deepEqual(braces("{a,b}"), ["(a|b)"]); + assert.deepEqual(braces(["{a,a}", "{a,b}"], { expand: true, nodupes: true }), ["a", "b"]); + assert.deepEqual(braces.expand("{,a}", { noempty: true }), ["a"]); + for (const literal of [ + '"' + nested(150) + '"', + "[" + nested(150) + "]", + "\\{".repeat(150) + "x" + "\\}".repeat(150), + ]) + assert.doesNotThrow(() => braces(literal)); + assert.equal(braces.stringify(braces.parse("a/{b,c}/d")), "a/{b,c}/d"); + assert.throws(() => braces.expand("{1..2000}"), /range limit/u); +}); + +test("preserves installed glob consumers and actual build-tool CLI behavior", () => { + assert.deepEqual(match(["a.ts", "b.js", "c.md"], ["*.{ts,js}"]), ["a.ts", "b.js"]); + const directory = mkdtempSync(join(tmpdir(), "diffex-braces-")); + try { + for (const file of ["a.txt", "b.txt", ".hidden.txt", "skip.md"]) writeFileSync(join(directory, file), "fixture"); + assert.deepEqual(glob.sync(["*.{txt,md}"], { cwd: directory, dot: true }).sort(), [ + ".hidden.txt", + "a.txt", + "b.txt", + "skip.md", + ]); + const output = join(directory, "out"); + mkdirSync(output); + const copied = spawnSync(process.execPath, [require.resolve("shx/lib/cli.js"), "cp", "*.{txt,md}", output], { + cwd: directory, + encoding: "utf8", + timeout: 10_000, + }); + assert.ifError(copied.error); + assert.equal(copied.status, 0, copied.stderr); + assert.deepEqual(readdirSync(output).sort(), ["a.txt", "b.txt", "skip.md"]); + assert.throws(() => glob.sync([nested(4000)], { cwd: directory, dot: true }), /maximum depth/u); + assert.deepEqual(match(["x"], [nested(4000)]), []); + const rejected = spawnSync(process.execPath, [require.resolve("shx/lib/cli.js"), "ls", nested(4000)], { + cwd: directory, + encoding: "utf8", + timeout: 10_000, + }); + assert.ifError(rejected.error); + assert.equal(rejected.signal, null); + assert.equal(rejected.status, 2); + assert.doesNotMatch(rejected.stderr, /Maximum call stack|RangeError/u); + } finally { + rmSync(directory, { recursive: true, force: true }); + } +}); diff --git a/vendor/braces/LICENSE b/vendor/braces/LICENSE new file mode 100644 index 000000000..9af4a67d2 --- /dev/null +++ b/vendor/braces/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-present, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/braces/README.md b/vendor/braces/README.md new file mode 100644 index 000000000..c027b6bce --- /dev/null +++ b/vendor/braces/README.md @@ -0,0 +1,49 @@ +# Local braces security patch + +This private package preserves the upstream `braces` 3.0.3 API and MIT license while bounding nesting to address [GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm). +It is named `@diffex-cloud/braces` at version `3.0.3-diffex.1` because this is our reviewed patch, not an upstream fixed release. +Each consuming repository wires npm overrides to the affected dependencies and tests the installed consumer rather than changing its functionality. +Diffex uses a root override because npm 10 does not reliably propagate an ancestor-scoped override through workspace dependencies. +Its current affected dependency chain is the development tool shx; the local patch is not included in shipped production locks. + +## Provenance + +The source is copied from the immutable [npm braces 3.0.3 tarball](https://registry.npmjs.org/braces/-/braces-3.0.3.tgz). +Its npm integrity is `sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==` and SHA-1 is `490332f40919452272d55a8480adc0c441358789`. +The library files are source, not generated code. +They retain upstream formatting to make the patch easy to compare. +The unchanged upstream MIT license is in `LICENSE`. +The private manifest pins the existing `fill-range` dependency to the reviewed version `7.1.1`. + +The original SHA-256 fingerprints are: + +| File | Original SHA-256 | +| ------------------ | ------------------------------------------------------------------ | +| `index.js` | `332ea07c7b006361aad12aa994ca75dc1db8e8382b884909e2f38f10b85c88a4` | +| `lib/compile.js` | `dc98f22eee3d511785d92a00758d5f0d48efed5f5813bdecc2de430c529b5c9f` | +| `lib/constants.js` | `c18ac5adb57308f1ce42a28552da3a31f5d83709743ebd9a636336813a744d4b` | +| `lib/expand.js` | `41ccc196ebfa7b7781a634e721eb744e4e7bcb54cba427a7e3d6806a1b9e58f7` | +| `lib/parse.js` | `e572166565f15fa6ad9865ae49d678218e32aabfd1b3720f6d0d43d39800d310` | +| `lib/stringify.js` | `379f22d77bfa1478341ccd49c5e4267464aabcbba03558bab332aac23fc6f23a` | +| `lib/utils.js` | `b5a7596aa67730412b3c029ef09e84e6b67b8e445cffd35d1d295549c89066c7` | +| `LICENSE` | `35bdd8a44339719441900fb50fbefc5e2dca1ca662cbaed7a687de842c8b70f2` | + +## Patch and verification + +The parser bounds combined brace and parenthesis nesting to 100 structural levels. +Compile, expand, and stringify independently bound recursive internal nodes, including caller-supplied ASTs. +Expansion parent traversal and recursive array helpers also have fixed bounds, and AST text values must be strings to prevent unchecked native array coercion. +Caller options cannot raise or disable these bounds. +Escaped, quoted, and character-class literal braces retain upstream behavior. +This addresses nesting exhaustion; it does not claim to bound every combinatorial expansion or other resource risk. + +Consuming repository tests exercise the actual affected dependency path, micromatch and fast-glob compatibility, public AST entry points, depth boundaries, cycles, alternatives, ranges, and literal handling. +Docker install stages must copy this package before installing local file dependencies. +`npm audit` checks registry dependencies but does not independently establish the security of this private source. +The source requires manual review and the targeted security tests in addition to the repository checks. + +## Retirement + +Replace the override with an upstream fixed release once its patch, compatibility, and advisory status have been verified. +Remove this private package and its formatting exceptions at that time, while keeping regression coverage for the affected consumer. +Do not relabel this package as an unaffected upstream version or suppress the advisory. diff --git a/vendor/braces/index.js b/vendor/braces/index.js new file mode 100644 index 000000000..d222c13b5 --- /dev/null +++ b/vendor/braces/index.js @@ -0,0 +1,170 @@ +'use strict'; + +const stringify = require('./lib/stringify'); +const compile = require('./lib/compile'); +const expand = require('./lib/expand'); +const parse = require('./lib/parse'); + +/** + * Expand the given pattern or create a regex-compatible string. + * + * ```js + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {String} + * @api public + */ + +const braces = (input, options = {}) => { + let output = []; + + if (Array.isArray(input)) { + for (const pattern of input) { + const result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); + } + } + } else { + output = [].concat(braces.create(input, options)); + } + + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; +}; + +/** + * Parse the given `str` with the given `options`. + * + * ```js + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); + * ``` + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST + * @api public + */ + +braces.parse = (input, options = {}) => parse(input, options); + +/** + * Creates a braces string from an AST, or an AST node. + * + * ```js + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); + } + return stringify(input, options); +}; + +/** + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. + * + * ```js + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + return compile(input, options); +}; + +/** + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. + * + * ```js + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + + let result = expand(input, options); + + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); + } + + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; + } + + return result; +}; + +/** + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. + * + * ```js + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; + } + + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; + +/** + * Expose "braces" + */ + +module.exports = braces; diff --git a/vendor/braces/lib/compile.js b/vendor/braces/lib/compile.js new file mode 100644 index 000000000..15edb2418 --- /dev/null +++ b/vendor/braces/lib/compile.js @@ -0,0 +1,61 @@ +'use strict'; + +const fill = require('fill-range'); +const utils = require('./utils'); + +const compile = (ast, options = {}) => { + const walk = (node, parent = {}, depth = 0) => { + utils.checkNode(node, depth); + const invalidBlock = utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; + const invalid = invalidBlock === true || invalidNode === true; + const prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; + + if (node.isOpen === true) { + return prefix + node.value; + } + + if (node.isClose === true) { + console.log('node.isClose', prefix, node.value); + return prefix + node.value; + } + + if (node.type === 'open') { + return invalid ? prefix + node.value : '('; + } + + if (node.type === 'close') { + return invalid ? prefix + node.value : ')'; + } + + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; + } + + if (node.value) { + return node.value; + } + + if (node.nodes && node.ranges > 0) { + const args = utils.reduce(node.nodes); + const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); + + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } + } + + if (node.nodes) { + for (const child of node.nodes) { + output += walk(child, node, depth + 1); + } + } + + return output; + }; + + return walk(ast); +}; + +module.exports = compile; diff --git a/vendor/braces/lib/constants.js b/vendor/braces/lib/constants.js new file mode 100644 index 000000000..2bb3b8840 --- /dev/null +++ b/vendor/braces/lib/constants.js @@ -0,0 +1,57 @@ +'use strict'; + +module.exports = { + MAX_LENGTH: 10000, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ +}; diff --git a/vendor/braces/lib/expand.js b/vendor/braces/lib/expand.js new file mode 100644 index 000000000..fada7ed5e --- /dev/null +++ b/vendor/braces/lib/expand.js @@ -0,0 +1,120 @@ +'use strict'; + +const fill = require('fill-range'); +const stringify = require('./stringify'); +const utils = require('./utils'); + +const append = (queue = '', stash = '', enclose = false, depth = 0) => { + utils.checkDepth(depth); + const result = []; + + queue = [].concat(queue); + stash = [].concat(stash); + + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; + } + + for (const item of queue) { + if (Array.isArray(item)) { + for (const value of item) { + result.push(append(value, stash, enclose, depth + 1)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose, depth + 1) : item + ele); + } + } + } + return utils.flatten(result); +}; + +const expand = (ast, options = {}) => { + const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; + + const walk = (node, parent = {}, depth = 0) => { + utils.checkNode(node, depth); + node.queue = []; + + let p = parent; + let q = parent.queue; + let parentDepth = 0; + + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + utils.checkDepth(++parentDepth); + p = p.parent; + q = p.queue; + } + + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; + } + + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; + } + + if (node.nodes && node.ranges > 0) { + const args = utils.reduce(node.nodes); + + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } + + q.push(append(q.pop(), range)); + node.nodes = []; + return; + } + + const enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; + parentDepth = 0; + + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + utils.checkDepth(++parentDepth); + block = block.parent; + queue = block.queue; + } + + for (let i = 0; i < node.nodes.length; i++) { + const child = node.nodes[i]; + utils.checkNode(child, depth + 1); + + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } + + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } + + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } + + if (child.nodes) { + walk(child, node, depth + 1); + } + } + + return queue; + }; + + return utils.flatten(walk(ast)); +}; + +module.exports = expand; diff --git a/vendor/braces/lib/parse.js b/vendor/braces/lib/parse.js new file mode 100644 index 000000000..70cdee2f8 --- /dev/null +++ b/vendor/braces/lib/parse.js @@ -0,0 +1,334 @@ +'use strict'; + +const stringify = require('./stringify'); +const utils = require('./utils'); + +/** + * Constants + */ + +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = require('./constants'); + +/** + * parse + */ + +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + const opts = options || {}; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } + + const ast = { type: 'root', input, nodes: [] }; + const stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + const length = input.length; + let index = 0; + let depth = 0; + let value; + + /** + * Helpers + */ + + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; + } + + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; + } + + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; + + push({ type: 'bos' }); + + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); + + /** + * Invalid chars + */ + + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; + } + + /** + * Escaped chars + */ + + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; + } + + /** + * Right square bracket (literal): ']' + */ + + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; + } + + /** + * Left square bracket: '[' + */ + + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + + let next; + + while (index < length && (next = advance())) { + value += next; + + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } + + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; + + if (brackets === 0) { + break; + } + } + } + + push({ type: 'text', value }); + continue; + } + + /** + * Parentheses + */ + + if (value === CHAR_LEFT_PARENTHESES) { + utils.checkDepth(stack.length); + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; + } + + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; + } + + /** + * Quotes: '|"|` + */ + + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + const open = value; + let next; + + if (options.keepQuotes !== true) { + value = ''; + } + + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } + + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } + + value += next; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Left curly brace: '{' + */ + + if (value === CHAR_LEFT_CURLY_BRACE) { + utils.checkDepth(stack.length); + depth++; + + const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + const brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; + + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; + } + + /** + * Right curly brace: '}' + */ + + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } + + const type = 'close'; + block = stack.pop(); + block.close = true; + + push({ type, value }); + depth--; + + block = stack[stack.length - 1]; + continue; + } + + /** + * Comma: ',' + */ + + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + const open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } + + push({ type: 'comma', value }); + block.commas++; + continue; + } + + /** + * Dot: '.' + */ + + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + const siblings = block.nodes; + + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + const before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; + } + + /** + * Text + */ + + push({ type: 'text', value }); + } + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + const parent = stack[stack.length - 1]; + const index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); + } + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; +}; + +module.exports = parse; diff --git a/vendor/braces/lib/stringify.js b/vendor/braces/lib/stringify.js new file mode 100644 index 000000000..94ddda245 --- /dev/null +++ b/vendor/braces/lib/stringify.js @@ -0,0 +1,32 @@ +'use strict'; + +const utils = require('./utils'); + +module.exports = (ast, options = {}) => { + const stringify = (node, parent = {}, depth = 0) => { + utils.checkNode(node, depth); + const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; + + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; + } + + if (node.value) { + return node.value; + } + + if (node.nodes) { + for (const child of node.nodes) { + output += stringify(child, {}, depth + 1); + } + } + return output; + }; + + return stringify(ast); +}; diff --git a/vendor/braces/lib/utils.js b/vendor/braces/lib/utils.js new file mode 100644 index 000000000..9f6353ad9 --- /dev/null +++ b/vendor/braces/lib/utils.js @@ -0,0 +1,136 @@ +'use strict'; + +// Bound recursive work independently of caller-supplied AST depth fields. +exports.checkDepth = depth => { + if (depth > 100) throw new SyntaxError('Pattern nesting exceeds maximum depth (100)'); +}; + +exports.checkNode = (node, depth) => { + if (node.nodes) exports.checkDepth(depth); + if (node.value !== undefined && typeof node.value !== 'string') { + throw new TypeError('AST values must be strings'); + } +}; + +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); + } + return false; +}; + +/** + * Find a node of the given type + */ + +exports.find = (node, type) => node.nodes.find(node => node.type === type); + +/** + * Find a node of the given type + */ + +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; +}; + +/** + * Escape the given node with '\\' before node.value + */ + +exports.escapeNode = (block, n = 0, type) => { + const node = block.nodes[n]; + if (!node) return; + + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; + } + } +}; + +/** + * Returns true if the given brace node should be enclosed in literal braces + */ + +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a brace node is invalid. + */ + +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a node is an open or close node + */ + +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; +}; + +/** + * Reduce an array of text nodes. + */ + +exports.reduce = nodes => nodes.reduce((acc, node) => { + exports.checkNode(node, 0); + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); + +/** + * Flatten an array + */ + +exports.flatten = (...args) => { + const result = []; + + const flat = (arr, depth = 0) => { + exports.checkDepth(depth); + for (let i = 0; i < arr.length; i++) { + const ele = arr[i]; + + if (Array.isArray(ele)) { + flat(ele, depth + 1); + continue; + } + + if (ele !== undefined) { + result.push(ele); + } + } + return result; + }; + + flat(args); + return result; +}; diff --git a/vendor/braces/package.json b/vendor/braces/package.json new file mode 100644 index 000000000..5a73b5e87 --- /dev/null +++ b/vendor/braces/package.json @@ -0,0 +1,18 @@ +{ + "name": "@diffex-cloud/braces", + "version": "3.0.3-diffex.1", + "private": true, + "description": "Reviewed local depth-guard patch of upstream braces 3.0.3", + "type": "commonjs", + "main": "index.js", + "license": "MIT", + "files": [ + "index.js", + "lib", + "LICENSE", + "README.md" + ], + "dependencies": { + "fill-range": "7.1.1" + } +}