diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8ac85850..f1273ff9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,9 @@ updates: directory: /clients/typescript schedule: interval: weekly + ignore: + - dependency-name: "@types/node" + update-types: ["version-update:semver-major"] - package-ecosystem: uv directory: /clients/python schedule: diff --git a/.github/workflows/dependency-validation.yml b/.github/workflows/dependency-validation.yml new file mode 100644 index 00000000..b1116b56 --- /dev/null +++ b/.github/workflows/dependency-validation.yml @@ -0,0 +1,37 @@ +name: Dependency merge validation + +on: + pull_request: + +permissions: + contents: read + +jobs: + dependency-proof: + if: github.head_ref == 'chore/dependency-fixes-proof-20261014' + name: Full dependency proof + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v4 + with: + node-version-file: .node-version + cache: pnpm + - uses: actions/setup-python@v7 + with: + python-version: "3.12" + - run: pip install uv==0.9.18 + - run: pnpm setup:dev + - run: pnpm check + - run: pnpm security:audit + - run: pnpm verify:architecture + - name: Upload verification evidence + if: always() + uses: actions/upload-artifact@v7 + with: + name: dependency-proof + path: scripts/verify/.run/ + include-hidden-files: true + retention-days: 7 diff --git a/assets/banner.svg b/assets/banner.svg index d9116cb2..e6ca36df 100644 --- a/assets/banner.svg +++ b/assets/banner.svg @@ -1,4 +1,5 @@ + SQL-FS diff --git a/biome.json b/biome.json index 207a0cf3..2c1db07d 100644 --- a/biome.json +++ b/biome.json @@ -1,17 +1,15 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json", + "$schema": "https://biomejs.dev/schemas/2.5.15/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, - "organizeImports": { - "enabled": true - }, + "assist": { "actions": { "source": { "organizeImports": "on" } } }, "linter": { "enabled": true, "rules": { - "recommended": true, + "preset": "recommended", "correctness": { "noUnusedImports": "error", "noUnusedVariables": "error" @@ -27,6 +25,14 @@ "lineWidth": 120 }, "files": { - "ignore": ["node_modules", "dist", "*.sql", "scripts", "clients/python", "tools/oxlint/anti-slop"] + "includes": [ + "**", + "!**/node_modules", + "!**/dist", + "!**/*.sql", + "!**/scripts", + "!**/clients/python", + "!**/tools/oxlint/anti-slop" + ] } } diff --git a/clients/typescript/package.json b/clients/typescript/package.json index c897ebfc..d3dcc4ae 100644 --- a/clients/typescript/package.json +++ b/clients/typescript/package.json @@ -13,7 +13,11 @@ "import": "./dist/index.js" } }, - "files": ["dist", "README.md", "LICENSE"], + "files": [ + "dist", + "README.md", + "LICENSE" + ], "scripts": { "build": "tsc -p tsconfig.json", "check:version": "node scripts/check-version.mjs", @@ -25,8 +29,8 @@ }, "packageManager": "pnpm@10.30.3", "devDependencies": { - "@types/node": "^22.0.0", + "@types/node": "^22.20.5", "typescript": "7.0.2", - "vitest": "^3.1.0" + "vitest": "^5.0.3" } } diff --git a/clients/typescript/pnpm-lock.yaml b/clients/typescript/pnpm-lock.yaml index ea07be8f..c41f5fe6 100644 --- a/clients/typescript/pnpm-lock.yaml +++ b/clients/typescript/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.19 + specifier: ^22.20.5 + version: 22.20.5 typescript: specifier: 7.0.2 version: 7.0.2 vitest: - specifier: ^3.1.0 - version: 3.2.6(@types/node@22.19.19) + specifier: ^5.0.3 + version: 5.0.4(@types/node@22.20.5)(vite@7.3.5(@types/node@22.20.5)) packages: @@ -176,9 +176,19 @@ packages: cpu: [x64] os: [win32] + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@rollup/rollup-android-arm-eabi@4.61.1': resolution: {integrity: sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==} cpu: [arm] @@ -326,8 +336,8 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/node@22.19.19': - resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + '@types/node@22.20.5': + resolution: {integrity: sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==} '@typescript/typescript-aix-ppc64@7.0.2': resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} @@ -449,66 +459,30 @@ packages: cpu: [x64] os: [win32] - '@vitest/expect@3.2.6': - resolution: {integrity: sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==} - - '@vitest/mocker@3.2.6': - resolution: {integrity: sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==} + '@vitest/mocker@5.0.4': + resolution: {integrity: sha512-tqAlrYWce4iUxhr3ncNohejtCTOcHeE8XWrSNZY3OhPoDn01yeGv+gnaBy64ATp7o6pb03eIbBAjzmibpc9vIQ==} peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + msw: ^2.4.9 || ^3.0.0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.6': - resolution: {integrity: sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==} - - '@vitest/runner@3.2.6': - resolution: {integrity: sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==} - - '@vitest/snapshot@3.2.6': - resolution: {integrity: sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==} - - '@vitest/spy@3.2.6': - resolution: {integrity: sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==} - - '@vitest/utils@3.2.6': - resolution: {integrity: sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==} + '@vitest/spy@5.0.4': + resolution: {integrity: sha512-MZKk/gSkm2q+ICobMxCpH1mA+cCAWm8WV7UhxlqGjq/sJ3AGc1BqFOs5CRVXxH78wQtme9q/NAAgBquj4AcyMw==} assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.3.0: + resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==} engines: {node: '>=18'} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} esbuild@0.27.7: resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} @@ -518,8 +492,8 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} fdir@6.5.0: @@ -536,29 +510,17 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + magic-string@1.4.3: + resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==} nanoid@3.3.12: resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} + obug@3.0.0: + resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==} + engines: {node: '>=12.20.0'} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -567,6 +529,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -576,44 +542,25 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.3.0: + resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + tinybench@6.2.2: + resolution: {integrity: sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==} + engines: {node: '>=20.0.0'} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.3.1: + resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} + engines: {node: '>=18'} tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} - engines: {node: '>=14.0.0'} - typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} @@ -622,11 +569,6 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - vite@7.3.5: resolution: {integrity: sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==} engines: {node: ^20.19.0 || >=22.12.0} @@ -667,26 +609,39 @@ packages: yaml: optional: true - vitest@3.2.6: - resolution: {integrity: sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@5.0.4: + resolution: {integrity: sha512-z0WxZRV2Sg48wF0FSgMq3TFG8JS38/Qr96vZVZdX6+Em9raQTvnXQvdTFJe2m3rfyJnEHeHQ/snceIdi8D1pVg==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.6 - '@vitest/ui': 3.2.6 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.4 + '@vitest/browser-preview': 5.0.4 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.4 + '@vitest/coverage-v8': 5.0.4 + '@vitest/ui': 5.0.4 happy-dom: '*' jsdom: '*' + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@opentelemetry/api': optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -695,9 +650,9 @@ packages: jsdom: optional: true - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} + why-is-node-running@3.2.1: + resolution: {integrity: sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==} + engines: {node: '>=20.11'} hasBin: true snapshots: @@ -780,8 +735,17 @@ snapshots: '@esbuild/win32-x64@0.27.7': optional: true + '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@rollup/rollup-android-arm-eabi@4.61.1': optional: true @@ -866,7 +830,7 @@ snapshots: '@types/estree@1.0.9': {} - '@types/node@22.19.19': + '@types/node@22.20.5': dependencies: undici-types: 6.21.0 @@ -930,69 +894,22 @@ snapshots: '@typescript/typescript-win32-x64@7.0.2': optional: true - '@vitest/expect@3.2.6': - dependencies: - '@types/chai': 5.2.3 - '@vitest/spy': 3.2.6 - '@vitest/utils': 3.2.6 - chai: 5.3.3 - tinyrainbow: 2.0.0 - - '@vitest/mocker@3.2.6(vite@7.3.5(@types/node@22.19.19))': + '@vitest/mocker@5.0.4(vite@7.3.5(@types/node@22.20.5))': dependencies: - '@vitest/spy': 3.2.6 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.4 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.4.3 optionalDependencies: - vite: 7.3.5(@types/node@22.19.19) - - '@vitest/pretty-format@3.2.6': - dependencies: - tinyrainbow: 2.0.0 - - '@vitest/runner@3.2.6': - dependencies: - '@vitest/utils': 3.2.6 - pathe: 2.0.3 - strip-literal: 3.1.0 - - '@vitest/snapshot@3.2.6': - dependencies: - '@vitest/pretty-format': 3.2.6 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@3.2.6': - dependencies: - tinyspy: 4.0.4 + vite: 7.3.5(@types/node@22.20.5) - '@vitest/utils@3.2.6': - dependencies: - '@vitest/pretty-format': 3.2.6 - loupe: 3.2.1 - tinyrainbow: 2.0.0 + '@vitest/spy@5.0.4': {} assertion-error@2.0.1: {} - cac@6.7.14: {} - - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 - - check-error@2.1.3: {} + chai@6.3.0: {} - debug@4.4.3: - dependencies: - ms: 2.1.3 - - deep-eql@5.0.2: {} - - es-module-lexer@1.7.0: {} + es-module-lexer@2.3.2: {} esbuild@0.27.7: optionalDependencies: @@ -1027,35 +944,33 @@ snapshots: dependencies: '@types/estree': 1.0.9 - expect-type@1.3.0: {} + expect-type@1.4.0: {} fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + fsevents@2.3.3: optional: true - js-tokens@9.0.1: {} - - loupe@3.2.1: {} - - magic-string@0.30.21: + magic-string@1.4.3: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - ms@2.1.3: {} + '@jridgewell/sourcemap-codec': 1.6.0 nanoid@3.3.12: {} - pathe@2.0.3: {} - - pathval@2.0.1: {} + obug@3.0.0: {} picocolors@1.1.1: {} picomatch@4.0.4: {} + picomatch@4.0.7: {} + postcss@8.5.15: dependencies: nanoid: 3.3.12 @@ -1093,32 +1008,18 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.61.1 fsevents: 2.3.3 - siginfo@2.0.0: {} - source-map-js@1.2.1: {} - stackback@0.0.2: {} - - std-env@3.10.0: {} - - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 + std-env@4.3.0: {} - tinybench@2.9.0: {} + tinybench@6.2.2: {} - tinyexec@0.3.2: {} + tinyexec@1.3.1: {} tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@4.0.4: {} + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 typescript@7.0.2: optionalDependencies: @@ -1145,28 +1046,7 @@ snapshots: undici-types@6.21.0: {} - vite-node@3.2.4(@types/node@22.19.19): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 7.3.5(@types/node@22.19.19) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@7.3.5(@types/node@22.19.19): + vite@7.3.5(@types/node@22.20.5): dependencies: esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) @@ -1175,51 +1055,28 @@ snapshots: rollup: 4.61.1 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 22.19.19 + '@types/node': 22.20.5 fsevents: 2.3.3 - vitest@3.2.6(@types/node@22.19.19): + vitest@5.0.4(@types/node@22.20.5)(vite@7.3.5(@types/node@22.20.5)): dependencies: '@types/chai': 5.2.3 - '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(vite@7.3.5(@types/node@22.19.19)) - '@vitest/pretty-format': 3.2.6 - '@vitest/runner': 3.2.6 - '@vitest/snapshot': 3.2.6 - '@vitest/spy': 3.2.6 - '@vitest/utils': 3.2.6 - chai: 5.3.3 - debug: 4.4.3 - expect-type: 1.3.0 - magic-string: 0.30.21 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 0.3.2 + '@vitest/mocker': 5.0.4(vite@7.3.5(@types/node@22.20.5)) + chai: 6.3.0 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 1.4.3 + obug: 3.0.0 + picomatch: 4.0.7 + std-env: 4.3.0 + tinybench: 6.2.2 + tinyexec: 1.3.1 tinyglobby: 0.2.17 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 - vite: 7.3.5(@types/node@22.19.19) - vite-node: 3.2.4(@types/node@22.19.19) - why-is-node-running: 2.3.0 + vite: 7.3.5(@types/node@22.20.5) + why-is-node-running: 3.2.1 optionalDependencies: - '@types/node': 22.19.19 + '@types/node': 22.20.5 transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 + + why-is-node-running@3.2.1: {} diff --git a/clients/typescript/src/http.ts b/clients/typescript/src/http.ts index 9146e759..8f880196 100644 --- a/clients/typescript/src/http.ts +++ b/clients/typescript/src/http.ts @@ -4,8 +4,8 @@ import { ExecTimeoutError, NotFoundError, RateLimitError, - SQLFSError, ServerError, + SQLFSError, TransportError, ValidationError, } from "./errors.js"; diff --git a/clients/typescript/src/index.ts b/clients/typescript/src/index.ts index 72657d1f..1c81abb8 100644 --- a/clients/typescript/src/index.ts +++ b/clients/typescript/src/index.ts @@ -1,4 +1,4 @@ -export { Client, SandboxesResource, type ClientOptions, type CreateSandboxOptions } from "./client.js"; +export { Client, type ClientOptions, type CreateSandboxOptions, SandboxesResource } from "./client.js"; export { AuthError, ConflictError, @@ -23,15 +23,15 @@ export { type TreeEntry, } from "./models.js"; export { - FilesAPI, - Sandbox, type DeleteOptions, type ExecBatchOptions, type ExecBatchScript, type ExecOptions, type ExecStreamOptions, type FileContent, + FilesAPI, type MkdirOptions, + Sandbox, type TreeOptions, } from "./sandbox.js"; export { version } from "./version.js"; diff --git a/clients/typescript/src/sandbox.ts b/clients/typescript/src/sandbox.ts index f3886e01..f6be5a99 100644 --- a/clients/typescript/src/sandbox.ts +++ b/clients/typescript/src/sandbox.ts @@ -1,18 +1,18 @@ import { SQLFSError, TransportError, ValidationError } from "./errors.js"; -import { type Transport, encodePath, iterSseEvents, raiseApiError, statusForStreamError } from "./http.js"; +import { encodePath, iterSseEvents, raiseApiError, statusForStreamError, type Transport } from "./http.js"; import { defaultMaxFileSize, isRecord, readJsonObject } from "./internal.js"; import { type BatchExecResult, + batchExecResultFromApi, type ExecResult, + execResultFromApi, type FileStat, + fileStatFromApi, ReadResult, type SandboxRecord, type StreamEvent, - type TreeEntry, - batchExecResultFromApi, - execResultFromApi, - fileStatFromApi, streamEventFromSse, + type TreeEntry, treeEntryFromApi, } from "./models.js"; diff --git a/clients/typescript/tests/test-utils.ts b/clients/typescript/tests/test-utils.ts index 60649f3b..38f50381 100644 --- a/clients/typescript/tests/test-utils.ts +++ b/clients/typescript/tests/test-utils.ts @@ -11,7 +11,9 @@ export interface CapturedRequest { export function jsonResponse(status: number, body: unknown, headers?: HeadersInit): Response { const responseHeaders = new Headers({ "Content-Type": "application/json" }); - new Headers(headers).forEach((value, name) => responseHeaders.set(name, value)); + new Headers(headers).forEach((value, name) => { + responseHeaders.set(name, value); + }); return new Response(JSON.stringify(body), { status, headers: responseHeaders }); } diff --git a/clients/typescript/vitest.config.ts b/clients/typescript/vitest.config.ts index 88747caa..8d47b13c 100644 --- a/clients/typescript/vitest.config.ts +++ b/clients/typescript/vitest.config.ts @@ -3,5 +3,6 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { testTimeout: 30_000, + maxWorkers: 2, }, }); diff --git a/comparison/file-operations.comparison.test.ts b/comparison/file-operations.comparison.test.ts index 18cb9e28..ce903a9a 100644 --- a/comparison/file-operations.comparison.test.ts +++ b/comparison/file-operations.comparison.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { path, cleanupTestDir, createTestDir, runRealBash, setupFiles } from "./fixture-runner.js"; +import { cleanupTestDir, createTestDir, path, runRealBash, setupFiles } from "./fixture-runner.js"; describe("mkdir command - Real Bash Comparison", () => { let testDir: string; diff --git a/comparison/fixture-runner.ts b/comparison/fixture-runner.ts index 9339c43b..17cef3b6 100644 --- a/comparison/fixture-runner.ts +++ b/comparison/fixture-runner.ts @@ -444,4 +444,4 @@ export async function compareOutputs( return compareOutputsInternal(env, testDir, command, testFiles, testFile, options); } -export { path, fs }; +export { fs, path }; diff --git a/comparison/pipes-redirections.comparison.test.ts b/comparison/pipes-redirections.comparison.test.ts index 68556144..4694a135 100644 --- a/comparison/pipes-redirections.comparison.test.ts +++ b/comparison/pipes-redirections.comparison.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { fs, path, cleanupTestDir, compareOutputs, createTestDir, runRealBash, setupFiles } from "./fixture-runner.js"; +import { cleanupTestDir, compareOutputs, createTestDir, fs, path, runRealBash, setupFiles } from "./fixture-runner.js"; describe("Pipes - Real Bash Comparison", () => { let testDir: string; diff --git a/comparison/tee.comparison.test.ts b/comparison/tee.comparison.test.ts index ab6cb9f6..bc4239d1 100644 --- a/comparison/tee.comparison.test.ts +++ b/comparison/tee.comparison.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { fs, path, cleanupTestDir, createTestDir, runRealBash, setupFiles } from "./fixture-runner.js"; +import { cleanupTestDir, createTestDir, fs, path, runRealBash, setupFiles } from "./fixture-runner.js"; describe("tee command - Real Bash Comparison", () => { let testDir: string; diff --git a/lefthook.yml b/lefthook.yml index 416d73bb..d9d9f43d 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -2,7 +2,7 @@ pre-commit: jobs: - name: typescript-style glob: "*.{ts,tsx,js,mjs,json}" - run: pnpm exec biome check --files-ignore-unknown=true --no-errors-on-unmatched {staged_files} + run: pnpm exec biome check --error-on-warnings --files-ignore-unknown=true --no-errors-on-unmatched {staged_files} - name: typescript-oxlint glob: "*.{ts,tsx,js,mjs,cjs,json}" diff --git a/package.json b/package.json index 6b4744d5..bb71a00e 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "bench:remote-bash": "python3 scripts/benchmark_remote_bash.py", "typecheck": "tsc --noEmit", "lint": "pnpm lint:biome && pnpm lint:oxlint", - "lint:fix": "biome check --write . && pnpm lint:oxlint", + "lint:fix": "biome check --write --error-on-warnings . && pnpm lint:oxlint", "test": "vitest run", "test:watch": "vitest", "test:unit": "vitest run --exclude 'src/**/integration/**'", @@ -37,7 +37,7 @@ "changeset": "changeset", "changeset:version": "changeset version && node scripts/sync-openapi-version.mjs && pnpm install --lockfile-only", "prepare": "lefthook install", - "lint:biome": "biome check .", + "lint:biome": "biome check --error-on-warnings .", "lint:oxlint": "pnpm lint:oxlint:syntax && pnpm lint:oxlint:types", "lint:oxlint:syntax": "NODE_OPTIONS=--import=tsx oxlint --deny-warnings .", "lint:oxlint:types": "NODE_OPTIONS=--import=tsx oxlint -c .oxlintrc-type-aware.json --deny-warnings src clients/typescript" @@ -57,7 +57,7 @@ "zod": "^3.24.0" }, "devDependencies": { - "@biomejs/biome": "^1.9.0", + "@biomejs/biome": "^2.5.15", "@changesets/changelog-github": "^1.0.1", "@changesets/cli": "^3.0.3", "@oxlint/plugins": "1.87.0", diff --git a/plugins/sql-fs/skills/ts-sdk/examples/ingest-explore.ts b/plugins/sql-fs/skills/ts-sdk/examples/ingest-explore.ts index ecae3f30..48bcb440 100644 --- a/plugins/sql-fs/skills/ts-sdk/examples/ingest-explore.ts +++ b/plugins/sql-fs/skills/ts-sdk/examples/ingest-explore.ts @@ -14,7 +14,7 @@ * BASE_URL=... AUTH_SECRET=... npx tsx ingest-explore.ts /path/to/local/code */ -import { readFile, readdir } from "node:fs/promises"; +import { readdir, readFile } from "node:fs/promises"; import path from "node:path"; import { Client } from "sql-fs-sdk"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a36394dd..ab4a7220 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,8 +55,8 @@ importers: version: 3.25.76 devDependencies: '@biomejs/biome': - specifier: ^1.9.0 - version: 1.9.4 + specifier: ^2.5.15 + version: 2.5.15 '@changesets/changelog-github': specifier: ^1.0.1 version: 1.0.1 @@ -102,59 +102,59 @@ importers: packages: - '@biomejs/biome@1.9.4': - resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} + '@biomejs/biome@2.5.15': + resolution: {integrity: sha512-WZTW4slm/pdkh92K6t/3aEN++44JD1PQ7squ7RCMLI1flHGl43DVOIGXvCjHiZgBMO1V4uYxoFNtqrIA4qGuIQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.9.4': - resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} + '@biomejs/cli-darwin-arm64@2.5.15': + resolution: {integrity: sha512-BZVzFhJ/mUvTLMYbc9x6el0o2Uv5zP7bACYyhFb6fSc1giroXm7PL0a5KqMJ9F+/BnkYRjagD/ROSDVOZ6eapg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.9.4': - resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} + '@biomejs/cli-darwin-x64@2.5.15': + resolution: {integrity: sha512-V5Kw63V+fVGNFhFrizDxMbGXAzZCh8kYzJpy3GI6gTapWDg7bZK9oYC9CbVgQSEdTnupz0U5Efz8Ev+5vdBBXw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.9.4': - resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} + '@biomejs/cli-linux-arm64-musl@2.5.15': + resolution: {integrity: sha512-tGzZUTcJCV7tj5Adh/Gn6nR4MycqA3iohq2LEcrarAgRBkU0h0OKd2UzCRkOsOYOuUGaUJb4YmqRqyy2feGGSw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [musl] - '@biomejs/cli-linux-arm64@1.9.4': - resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} + '@biomejs/cli-linux-arm64@2.5.15': + resolution: {integrity: sha512-XaG7P7eeSLYETD3K9grfB0mQmpLQZjygdbsxekWBJAg4am79fGAtRpfRyNnTvXB2fZFNnJZG3nXm7HBat0+VUw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [glibc] - '@biomejs/cli-linux-x64-musl@1.9.4': - resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} + '@biomejs/cli-linux-x64-musl@2.5.15': + resolution: {integrity: sha512-IlxUcyxilVGPsE008x13pWdkTbU3nQpP2i9b5UrbOYj6goBkKsRX1XB7yJLcV+O1H9LBchIIm4adOaVLZBX0ZQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [musl] - '@biomejs/cli-linux-x64@1.9.4': - resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} + '@biomejs/cli-linux-x64@2.5.15': + resolution: {integrity: sha512-xE4iEW/3LqlYj9GFgGrFsFSH51dEEpUbYWBfeOv0q87WkUDxK2o/HhreSb7qMJqck70RVM6Lg96hgedcAYcOkA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [glibc] - '@biomejs/cli-win32-arm64@1.9.4': - resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} + '@biomejs/cli-win32-arm64@2.5.15': + resolution: {integrity: sha512-2kPKzhNlm8C+Ru3GcO0Me2ODkCBLrVOUNuyi84RJyWDVKAA4+Kjj3jMjL938lF6BRfvltC4vB2nPY9SvN51Ovg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.9.4': - resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} + '@biomejs/cli-win32-x64@2.5.15': + resolution: {integrity: sha512-yAzh4UqEImV6Hcy0zjUqNfJAsUhoD64FBQCdTG8Md/Z2wQeVP/ZmJ3XRYAs1g8J9fjTFyl2fCtc5FB5til47+g==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -2447,39 +2447,39 @@ packages: snapshots: - '@biomejs/biome@1.9.4': + '@biomejs/biome@2.5.15': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.9.4 - '@biomejs/cli-darwin-x64': 1.9.4 - '@biomejs/cli-linux-arm64': 1.9.4 - '@biomejs/cli-linux-arm64-musl': 1.9.4 - '@biomejs/cli-linux-x64': 1.9.4 - '@biomejs/cli-linux-x64-musl': 1.9.4 - '@biomejs/cli-win32-arm64': 1.9.4 - '@biomejs/cli-win32-x64': 1.9.4 + '@biomejs/cli-darwin-arm64': 2.5.15 + '@biomejs/cli-darwin-x64': 2.5.15 + '@biomejs/cli-linux-arm64': 2.5.15 + '@biomejs/cli-linux-arm64-musl': 2.5.15 + '@biomejs/cli-linux-x64': 2.5.15 + '@biomejs/cli-linux-x64-musl': 2.5.15 + '@biomejs/cli-win32-arm64': 2.5.15 + '@biomejs/cli-win32-x64': 2.5.15 - '@biomejs/cli-darwin-arm64@1.9.4': + '@biomejs/cli-darwin-arm64@2.5.15': optional: true - '@biomejs/cli-darwin-x64@1.9.4': + '@biomejs/cli-darwin-x64@2.5.15': optional: true - '@biomejs/cli-linux-arm64-musl@1.9.4': + '@biomejs/cli-linux-arm64-musl@2.5.15': optional: true - '@biomejs/cli-linux-arm64@1.9.4': + '@biomejs/cli-linux-arm64@2.5.15': optional: true - '@biomejs/cli-linux-x64-musl@1.9.4': + '@biomejs/cli-linux-x64-musl@2.5.15': optional: true - '@biomejs/cli-linux-x64@1.9.4': + '@biomejs/cli-linux-x64@2.5.15': optional: true - '@biomejs/cli-win32-arm64@1.9.4': + '@biomejs/cli-win32-arm64@2.5.15': optional: true - '@biomejs/cli-win32-x64@1.9.4': + '@biomejs/cli-win32-x64@2.5.15': optional: true '@borewit/text-codec@0.2.2': {} diff --git a/src/api/auth.ts b/src/api/auth.ts index ba29ee73..6c9ff003 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -24,7 +24,7 @@ import { createMiddleware } from "hono/factory"; import type { ContentfulStatusCode } from "hono/utils/http-status"; import { jwtVerify } from "jose"; import { constantTimeEqual } from "./lib/constant-time.js"; -import { DEFAULT_TENANT_ID, type TenantConfig, loadTenantConfig } from "./tenants.js"; +import { DEFAULT_TENANT_ID, loadTenantConfig, type TenantConfig } from "./tenants.js"; export type AuthVariables = { owner: string; diff --git a/src/api/commands/git-command.ts b/src/api/commands/git-command.ts index 0618dc41..48ddf913 100644 --- a/src/api/commands/git-command.ts +++ b/src/api/commands/git-command.ts @@ -19,8 +19,8 @@ import { AsyncLocalStorage } from "node:async_hooks"; import { posix } from "node:path"; -import { defineCommand } from "just-bash"; import type { Command, ExecResult, IFileSystem } from "just-bash"; +import { defineCommand } from "just-bash"; import { createGit } from "just-git"; import { flattenTree, readCommit, revParse } from "just-git/repo"; diff --git a/src/api/commands/node-command.ts b/src/api/commands/node-command.ts index 869482a4..42651cce 100644 --- a/src/api/commands/node-command.ts +++ b/src/api/commands/node-command.ts @@ -21,8 +21,8 @@ * Fixes: https://github.com/Hazzng/sql-fs/issues/76 */ -import { defineCommand } from "just-bash"; import type { CommandContext, ExecResult } from "just-bash"; +import { defineCommand } from "just-bash"; const HINT = `\ 'node' is not available in this sandbox. Use 'js-exec' instead: diff --git a/src/api/distributed-lock.ts b/src/api/distributed-lock.ts index 522efa18..2763fc96 100644 --- a/src/api/distributed-lock.ts +++ b/src/api/distributed-lock.ts @@ -13,8 +13,8 @@ import type { Redis } from "ioredis"; import { AcquireErrorBudget, DEFAULT_ACQUIRE_ERROR_BUDGET_MS, - type ProbeTicketHolder, getRedisCircuitBreaker, + type ProbeTicketHolder, } from "../redis/circuit-breaker.js"; import { preservesAmbiguousOutcome } from "./errors.js"; import { recordHeartbeatGap } from "./event-loop-monitor.js"; diff --git a/src/api/distributed-rw-lock.ts b/src/api/distributed-rw-lock.ts index 1a02186e..850a3faf 100644 --- a/src/api/distributed-rw-lock.ts +++ b/src/api/distributed-rw-lock.ts @@ -14,16 +14,18 @@ import type { Redis } from "ioredis"; import { AcquireErrorBudget, DEFAULT_ACQUIRE_ERROR_BUDGET_MS, + getRedisCircuitBreaker, type ProbeTicketHolder, type RedisCircuitBreaker, - getRedisCircuitBreaker, } from "../redis/circuit-breaker.js"; + export { LockAcquireTimeoutError, LockLostAfterCommitError, LockLostError } from "./distributed-lock.js"; + import { + jitteredDelayMs, LockAcquireTimeoutError, LockLostAfterCommitError, LockLostError, - jitteredDelayMs, logLockLostAfterCommit, } from "./distributed-lock.js"; import { preservesAmbiguousOutcome } from "./errors.js"; diff --git a/src/api/lib/batch-exec.ts b/src/api/lib/batch-exec.ts index b0a0333b..a5a9d9fe 100644 --- a/src/api/lib/batch-exec.ts +++ b/src/api/lib/batch-exec.ts @@ -1,7 +1,6 @@ import { preservesAmbiguousOutcome } from "../errors.js"; import { readOnlyContext } from "../read-only-context.js"; -import type { SessionManager } from "../session-manager.js"; -import type { Session } from "../session-manager.js"; +import type { Session, SessionManager } from "../session-manager.js"; export interface BatchScriptEntry { readonly id: string; diff --git a/src/api/lib/jwt.ts b/src/api/lib/jwt.ts index d2abb89a..1c16593c 100644 --- a/src/api/lib/jwt.ts +++ b/src/api/lib/jwt.ts @@ -3,7 +3,7 @@ * Used by CLI token generator and admin token endpoint. */ -import { SignJWT, jwtVerify } from "jose"; +import { jwtVerify, SignJWT } from "jose"; export interface SignTokenOptions { sub: string; diff --git a/src/api/lib/script-tx.ts b/src/api/lib/script-tx.ts index 798947a2..5bd2bae4 100644 --- a/src/api/lib/script-tx.ts +++ b/src/api/lib/script-tx.ts @@ -1,4 +1,4 @@ -import { type ScriptScope, runInScriptScope } from "../../sql-fs/script-scope.js"; +import { runInScriptScope, type ScriptScope } from "../../sql-fs/script-scope.js"; import { assertScriptLeaseHeld } from "./script-lease.js"; export async function runInScriptTx( diff --git a/src/api/migrations.ts b/src/api/migrations.ts index 84985eb1..2ce2c78a 100644 --- a/src/api/migrations.ts +++ b/src/api/migrations.ts @@ -9,7 +9,7 @@ * Fails closed: the first tenant error aborts the boot with a clear log line. */ -import { readFileSync, readdirSync } from "node:fs"; +import { readdirSync, readFileSync } from "node:fs"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import postgres from "postgres"; diff --git a/src/api/routes/files.ts b/src/api/routes/files.ts index e1bc93cd..193a8957 100644 --- a/src/api/routes/files.ts +++ b/src/api/routes/files.ts @@ -9,8 +9,8 @@ * US-067: GET /v1/sandboxes/:id/tree — list file tree */ -import { Hono } from "hono"; import type { Context, MiddlewareHandler } from "hono"; +import { Hono } from "hono"; import type { ContentfulStatusCode } from "hono/utils/http-status"; import type { FsStat } from "just-bash"; import { z } from "zod"; @@ -22,7 +22,7 @@ import { MAX_BULK_WRITE_FILES, MAX_FILE_WRITE_BYTES as MAX_RAW_FILE_WRITE_BYTES, } from "../lib/env.js"; -import { type EditOutcome, type WriteOutcome, editFile, ensureParentDir, writeFileAtPath } from "../lib/file-ops.js"; +import { type EditOutcome, editFile, ensureParentDir, type WriteOutcome, writeFileAtPath } from "../lib/file-ops.js"; import { retainedInputBytes } from "../lib/request-input.js"; import { runInScriptTx } from "../lib/script-tx.js"; import { diff --git a/src/api/server.ts b/src/api/server.ts index 6d9eeffb..0262e98e 100644 --- a/src/api/server.ts +++ b/src/api/server.ts @@ -28,8 +28,8 @@ import { } from "./event-loop-monitor.js"; import { loadExecLockOptions } from "./exec-lock-config.js"; import { IngressAdmission, loadIngressOptions } from "./ingress-admission.js"; -import { mcpOptionsResponse, withMcpCors } from "./mcp-cors.js"; import { handleMcpRequest, shutdownMcp, startMcpSessionSweeper } from "./mcp/server.js"; +import { mcpOptionsResponse, withMcpCors } from "./mcp-cors.js"; import { runMigrations } from "./migrations.js"; import { openapiSpec } from "./openapi-spec.js"; import { authRoutes } from "./routes/auth.js"; diff --git a/src/api/session-manager.ts b/src/api/session-manager.ts index 06a070d3..56834c41 100644 --- a/src/api/session-manager.ts +++ b/src/api/session-manager.ts @@ -15,15 +15,16 @@ import { logAudit } from "./lib/audit.js"; import { type ReadOnlyContext, readOnlyContext } from "./read-only-context.js"; import { sessionLeaseContext } from "./session-lease-context.js"; import { - type RuntimeOptions, - type SessionRuntime, buildGitIdentity, buildSandboxBaseEnv, createSessionRuntime, executeSessionRuntime, + type RuntimeOptions, + type SessionRuntime, } from "./session-runtime/engine.js"; -export { buildGitIdentity, buildSandboxBaseEnv, deriveExecGitCredentials } from "./session-runtime/engine.js"; + export type { RuntimeOptions, SessionScriptScope } from "./session-runtime/engine.js"; +export { buildGitIdentity, buildSandboxBaseEnv, deriveExecGitCredentials } from "./session-runtime/engine.js"; import { RuntimeAdmission, type RuntimeAdmissionOptions } from "./session-manager/runtime-admission.js"; import { @@ -34,12 +35,13 @@ import { sessionKey, } from "./session-manager/session-catalog.js"; import { TenantBackends, type TenantBackendsOptions } from "./session-manager/tenant-backends.js"; + export { RuntimeBackpressureError } from "./session-manager/runtime-admission.js"; export type { Session } from "./session-manager/session-catalog.js"; import { WorkerFileSystem, WorkerScriptScope } from "./worker-owner/filesystem.js"; import { assertWorkerMessageBudget } from "./worker-owner/message-budget.js"; -import { WorkerOwnerPool, type WorkerPoolOptions, loadWorkerPoolOptions } from "./worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool, type WorkerPoolOptions } from "./worker-owner/pool.js"; import type { ShellExecutionLimits } from "./worker-owner/protocol.js"; function asCoherentFs(fs: IFileSystem): ICoherentFs | undefined { diff --git a/src/api/session-runtime/engine.ts b/src/api/session-runtime/engine.ts index be8defc0..a1d02926 100644 --- a/src/api/session-runtime/engine.ts +++ b/src/api/session-runtime/engine.ts @@ -1,18 +1,19 @@ -import { Bash } from "just-bash"; import type { BashExecResult, ExecOptions, IFileSystem, SecurityViolation } from "just-bash"; -import { type ScriptScope, runInScriptScope } from "../../sql-fs/script-scope.js"; +import { Bash } from "just-bash"; +import { runInScriptScope, type ScriptScope } from "../../sql-fs/script-scope.js"; import { SessionScopedFs } from "../../sql-fs/session-scoped-fs.js"; import type { ICoherentFs, IScriptTxFs } from "../../sql-fs/sql-fs.js"; -import { type GitIdentity, createGitCommand, httpsOnlyGitFetch } from "../commands/git-command.js"; +import { createGitCommand, type GitIdentity, httpsOnlyGitFetch } from "../commands/git-command.js"; import { nodeCommand } from "../commands/node-command.js"; import { LockLostError } from "../distributed-lock.js"; -import { type ExecContext, consumeExecInput, execContext } from "../exec-context.js"; +import { consumeExecInput, type ExecContext, execContext } from "../exec-context.js"; import { logAudit } from "../lib/audit.js"; import { MAX_EXEC_FILE_BYTES } from "../lib/env.js"; import { posixNormalizePath } from "../lib/paths.js"; import { assertScriptLeaseHeld } from "../lib/script-lease.js"; import { readOnlyContext } from "../read-only-context.js"; import { sessionLeaseSignal } from "../session-lease-context.js"; + export type { ScriptScope as SessionScriptScope } from "../../sql-fs/script-scope.js"; export interface RuntimeOptions { diff --git a/src/api/tests/fixtures/commit-reply-gate.ts b/src/api/tests/fixtures/commit-reply-gate.ts index 53742366..2fdb6202 100644 --- a/src/api/tests/fixtures/commit-reply-gate.ts +++ b/src/api/tests/fixtures/commit-reply-gate.ts @@ -1,5 +1,5 @@ import { once } from "node:events"; -import { type Socket, createConnection, createServer } from "node:net"; +import { createConnection, createServer, type Socket } from "node:net"; export async function commitReplyGate(connectionString: string, committed: () => Promise) { const upstream = new URL(connectionString); diff --git a/src/api/tests/integration/git-network.integration.test.ts b/src/api/tests/integration/git-network.integration.test.ts index 4f8e8b65..c87861a0 100644 --- a/src/api/tests/integration/git-network.integration.test.ts +++ b/src/api/tests/integration/git-network.integration.test.ts @@ -1,4 +1,4 @@ -import { Bash, InMemoryFs, defineCommand } from "just-bash"; +import { Bash, defineCommand, InMemoryFs } from "just-bash"; import { createGit } from "just-git"; import { readCommit, resolveRef } from "just-git/repo"; import { type Auth, createServer } from "just-git/server"; diff --git a/src/api/tests/integration/git-sqlfs.integration.test.ts b/src/api/tests/integration/git-sqlfs.integration.test.ts index 3c5d39b0..51fcc1bd 100644 --- a/src/api/tests/integration/git-sqlfs.integration.test.ts +++ b/src/api/tests/integration/git-sqlfs.integration.test.ts @@ -5,7 +5,7 @@ import postgres from "postgres"; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { requireMigratedSchema } from "../../../sql-fs/tests/integration/helpers/schema-preconditions.js"; import { type RuntimeOptions, SessionManager } from "../../session-manager.js"; -import { type TenantConfig, loadTenantConfig } from "../../tenants.js"; +import { loadTenantConfig, type TenantConfig } from "../../tenants.js"; const SKIP = !process.env.DATABASE_URL; const TENANT_ID = "default"; diff --git a/src/api/tests/integration/heartbeat-gap.redis.integration.test.ts b/src/api/tests/integration/heartbeat-gap.redis.integration.test.ts index 0935bb43..b99ce93d 100644 --- a/src/api/tests/integration/heartbeat-gap.redis.integration.test.ts +++ b/src/api/tests/integration/heartbeat-gap.redis.integration.test.ts @@ -20,7 +20,7 @@ import { Redis } from "ioredis"; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest"; -import { LockLostAfterCommitError, execLockKey, withDistributedLock } from "../../distributed-lock.js"; +import { execLockKey, LockLostAfterCommitError, withDistributedLock } from "../../distributed-lock.js"; import { type RWLockKeys, rwLockKeys, withDistributedRWLock } from "../../distributed-rw-lock.js"; const SKIP = !process.env.REDIS_URL; diff --git a/src/api/tests/integration/multi-tenant.integration.test.ts b/src/api/tests/integration/multi-tenant.integration.test.ts index d2480d8e..56e6fe97 100644 --- a/src/api/tests/integration/multi-tenant.integration.test.ts +++ b/src/api/tests/integration/multi-tenant.integration.test.ts @@ -22,7 +22,7 @@ import { fileRoutes } from "../../routes/files.js"; import { ingestRoutes } from "../../routes/ingest.js"; import { sandboxRoutes } from "../../routes/sandboxes.js"; import { SessionManager } from "../../session-manager.js"; -import { type TenantConfig, loadTenantConfig } from "../../tenants.js"; +import { loadTenantConfig, type TenantConfig } from "../../tenants.js"; const AUTH_SECRET = "phase-5-multi-tenant-secret-at-least-32b"; const SKIP = !process.env.DATABASE_URL || !process.env.REDIS_URL; diff --git a/src/api/tests/integration/worker-error-lease.integration.test.ts b/src/api/tests/integration/worker-error-lease.integration.test.ts index ffb4dcd4..3447270f 100644 --- a/src/api/tests/integration/worker-error-lease.integration.test.ts +++ b/src/api/tests/integration/worker-error-lease.integration.test.ts @@ -1,6 +1,6 @@ import { createHash, randomUUID } from "node:crypto"; import { once } from "node:events"; -import { type IncomingMessage, type ServerResponse, createServer } from "node:http"; +import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; import { Worker } from "node:worker_threads"; import { Hono } from "hono"; import { Redis } from "ioredis"; diff --git a/src/api/tests/integration/worker-owner.failure.integration.test.ts b/src/api/tests/integration/worker-owner.failure.integration.test.ts index f32bc800..097355a4 100644 --- a/src/api/tests/integration/worker-owner.failure.integration.test.ts +++ b/src/api/tests/integration/worker-owner.failure.integration.test.ts @@ -12,7 +12,7 @@ import { SqlFs } from "../../../sql-fs/sql-fs.js"; import { requireMigratedSchema } from "../../../sql-fs/tests/integration/helpers/schema-preconditions.js"; import { rwLockKeys } from "../../distributed-rw-lock.js"; import { SessionManager } from "../../session-manager.js"; -import { type TenantConfig, loadTenantConfig } from "../../tenants.js"; +import { loadTenantConfig, type TenantConfig } from "../../tenants.js"; import { loadWorkerPoolOptions } from "../../worker-owner/pool.js"; import { workerRequestContext } from "../../worker-owner/request-context.js"; import { commitReplyGate } from "../fixtures/commit-reply-gate.js"; diff --git a/src/api/tests/integration/worker-owner.resources.integration.test.ts b/src/api/tests/integration/worker-owner.resources.integration.test.ts index 287a6865..6ae04b23 100644 --- a/src/api/tests/integration/worker-owner.resources.integration.test.ts +++ b/src/api/tests/integration/worker-owner.resources.integration.test.ts @@ -6,7 +6,7 @@ import { destroyPostgresSandbox } from "../../../sql-fs/index.js"; import { requireMigratedSchema } from "../../../sql-fs/tests/integration/helpers/schema-preconditions.js"; import { type RuntimeOptions, SessionManager } from "../../session-manager.js"; import { loadTenantConfig } from "../../tenants.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import type { OwnerCommand, OwnerCommandKind, OwnerResult } from "../../worker-owner/protocol.js"; import { workerRequestContext } from "../../worker-owner/request-context.js"; diff --git a/src/api/tests/integration/worker-replacement.integration.test.ts b/src/api/tests/integration/worker-replacement.integration.test.ts index 48440798..5b1c3d96 100644 --- a/src/api/tests/integration/worker-replacement.integration.test.ts +++ b/src/api/tests/integration/worker-replacement.integration.test.ts @@ -1,11 +1,11 @@ import { randomUUID } from "node:crypto"; import { Worker } from "node:worker_threads"; -import { type MockInstance, beforeAll, describe, expect, it, vi } from "vitest"; +import { beforeAll, describe, expect, it, type MockInstance, vi } from "vitest"; import { destroyPostgresSandbox } from "../../../sql-fs/index.js"; import { requireMigratedSchema } from "../../../sql-fs/tests/integration/helpers/schema-preconditions.js"; import { SessionManager } from "../../session-manager.js"; import { loadTenantConfig } from "../../tenants.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import type { OwnerIdentity, OwnerRequest } from "../../worker-owner/protocol.js"; function checkpoint() { diff --git a/src/api/tests/integration/worker-runtime-admission.integration.test.ts b/src/api/tests/integration/worker-runtime-admission.integration.test.ts index 8344e6e3..9242078f 100644 --- a/src/api/tests/integration/worker-runtime-admission.integration.test.ts +++ b/src/api/tests/integration/worker-runtime-admission.integration.test.ts @@ -3,7 +3,7 @@ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { requireMigratedSchema } from "../../../sql-fs/tests/integration/helpers/schema-preconditions.js"; import { type RuntimeOptions, SessionManager } from "../../session-manager.js"; import { loadTenantConfig } from "../../tenants.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import type { OwnerCommand, OwnerCommandKind, OwnerResult } from "../../worker-owner/protocol.js"; const TENANTS = ["worker-runtime-a", "worker-runtime-b"] as const; diff --git a/src/api/tests/integration/worker-runtime-prefix.integration.test.ts b/src/api/tests/integration/worker-runtime-prefix.integration.test.ts index a07d4447..e0f2705e 100644 --- a/src/api/tests/integration/worker-runtime-prefix.integration.test.ts +++ b/src/api/tests/integration/worker-runtime-prefix.integration.test.ts @@ -1,6 +1,6 @@ import { randomUUID } from "node:crypto"; import { once } from "node:events"; -import { type IncomingMessage, type ServerResponse, createServer } from "node:http"; +import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { PostgresDialect } from "../../../sql-fs/dialects/postgres.js"; import { SqlFs } from "../../../sql-fs/sql-fs.js"; diff --git a/src/api/tests/session-manager.script-tx.test.ts b/src/api/tests/session-manager.script-tx.test.ts index 9ef1f4d0..f016f10b 100644 --- a/src/api/tests/session-manager.script-tx.test.ts +++ b/src/api/tests/session-manager.script-tx.test.ts @@ -1,5 +1,5 @@ -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { SessionScopedFs } from "../../sql-fs/session-scoped-fs.js"; import type { IScriptTxFs } from "../../sql-fs/sql-fs.js"; diff --git a/src/api/tests/unit/admin.test.ts b/src/api/tests/unit/admin.test.ts index 05d4a72f..bf657e8e 100644 --- a/src/api/tests/unit/admin.test.ts +++ b/src/api/tests/unit/admin.test.ts @@ -3,7 +3,7 @@ */ import { Hono } from "hono"; -import { SignJWT, jwtVerify } from "jose"; +import { jwtVerify, SignJWT } from "jose"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { defaultRateLimitStore } from "../../rate-limit.js"; import { authRoutes } from "../../routes/auth.js"; diff --git a/src/api/tests/unit/auth-mcp-static.test.ts b/src/api/tests/unit/auth-mcp-static.test.ts index 7c248ae3..11ff5591 100644 --- a/src/api/tests/unit/auth-mcp-static.test.ts +++ b/src/api/tests/unit/auth-mcp-static.test.ts @@ -8,7 +8,7 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { type AuthVariables, type StaticMcpAuthConfig, createAuthMiddleware } from "../../auth.js"; +import { type AuthVariables, createAuthMiddleware, type StaticMcpAuthConfig } from "../../auth.js"; import type { TenantConfig } from "../../tenants.js"; const SECRET = "test-secret-at-least-32-bytes-long!!"; diff --git a/src/api/tests/unit/distributed-acquire-jitter.test.ts b/src/api/tests/unit/distributed-acquire-jitter.test.ts index 007ddedb..843ee96f 100644 --- a/src/api/tests/unit/distributed-acquire-jitter.test.ts +++ b/src/api/tests/unit/distributed-acquire-jitter.test.ts @@ -11,7 +11,7 @@ import type { Redis } from "ioredis"; import { afterEach, describe, expect, it, vi } from "vitest"; import { resetRedisCircuitBreakerForTest } from "../../../redis/circuit-breaker.js"; -import { LockAcquireTimeoutError, execLockKey, jitteredDelayMs, withDistributedLock } from "../../distributed-lock.js"; +import { execLockKey, jitteredDelayMs, LockAcquireTimeoutError, withDistributedLock } from "../../distributed-lock.js"; interface Entry { value: string; diff --git a/src/api/tests/unit/distributed-lock.circuit-breaker.test.ts b/src/api/tests/unit/distributed-lock.circuit-breaker.test.ts index 43fefd23..f5b13c51 100644 --- a/src/api/tests/unit/distributed-lock.circuit-breaker.test.ts +++ b/src/api/tests/unit/distributed-lock.circuit-breaker.test.ts @@ -9,7 +9,7 @@ import type { Redis } from "ioredis"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resetRedisCircuitBreakerForTest } from "../../../redis/circuit-breaker.js"; -import { LockAcquireTimeoutError, execLockKey, withDistributedLock } from "../../distributed-lock.js"; +import { execLockKey, LockAcquireTimeoutError, withDistributedLock } from "../../distributed-lock.js"; /** Redis fake that throws a connection-class error on every command (sustained outage). */ class DeadRedis { diff --git a/src/api/tests/unit/distributed-lock.test.ts b/src/api/tests/unit/distributed-lock.test.ts index e8229f2d..b560e868 100644 --- a/src/api/tests/unit/distributed-lock.test.ts +++ b/src/api/tests/unit/distributed-lock.test.ts @@ -7,10 +7,10 @@ import type { Redis } from "ioredis"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { + execLockKey, LockAcquireTimeoutError, LockLostAfterCommitError, LockLostError, - execLockKey, withDistributedLock, } from "../../distributed-lock.js"; diff --git a/src/api/tests/unit/event-loop-monitor.test.ts b/src/api/tests/unit/event-loop-monitor.test.ts index 7e828b03..d648ae34 100644 --- a/src/api/tests/unit/event-loop-monitor.test.ts +++ b/src/api/tests/unit/event-loop-monitor.test.ts @@ -1,14 +1,14 @@ /** * Unit tests for the F8 event-loop lag monitor (purely observational). * Covers the pure gap classifier, the structured `heartbeat_gap` emitter, and - * the `monitorEventLoopDelay`-backed boot histogram (real busy-loop, no timers - * faked — perf_hooks measures wall-clock). + * the `monitorEventLoopDelay`-backed boot histogram with a real busy-loop and native + * perf_hooks sampling. */ -import { afterEach, describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { - DEFAULT_STALL_THRESHOLD_MS, classifyHeartbeatGap, + DEFAULT_STALL_THRESHOLD_MS, eventLoopLagSnapshot, recordHeartbeatGap, resetEventLoopMonitorForTest, @@ -102,7 +102,10 @@ describe("recordHeartbeatGap", () => { }); describe("event-loop monitor lifecycle", () => { - afterEach(() => resetEventLoopMonitorForTest()); + afterEach(() => { + resetEventLoopMonitorForTest(); + vi.useRealTimers(); + }); it("snapshot is undefined before start and defined after", () => { expect(eventLoopLagSnapshot()).toBeUndefined(); @@ -203,6 +206,8 @@ describe("event-loop monitor lifecycle", () => { // 150 ms stall that would trip a 100 ms threshold must stay silent under a high one, or the // signal is a per-window chorus and worthless as an alert. it("stays silent when a real stall stays under the threshold", async () => { + // Flush the logging window only after native perf_hooks sampling records the real stall. + vi.useFakeTimers({ toFake: ["setInterval", "clearInterval"] }); const lines: string[] = []; startEventLoopMonitor({ sampleIntervalMs: 60, @@ -211,9 +216,10 @@ describe("event-loop monitor lifecycle", () => { log: (l) => lines.push(l), }); try { - await new Promise((res) => setTimeout(res, 40)); + await expect.poll(() => eventLoopLagSnapshot()?.maxMs).toBeGreaterThan(0); busyLoopMs(150); - await new Promise((res) => setTimeout(res, 140)); + await expect.poll(() => eventLoopLagSnapshot()?.maxMs).toBeGreaterThanOrEqual(100); + vi.advanceTimersByTime(60); } finally { stopEventLoopMonitor(); } diff --git a/src/api/tests/unit/exec-batch-outcome.test.ts b/src/api/tests/unit/exec-batch-outcome.test.ts index 8f969f5f..06d20ce1 100644 --- a/src/api/tests/unit/exec-batch-outcome.test.ts +++ b/src/api/tests/unit/exec-batch-outcome.test.ts @@ -1,7 +1,7 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { BashExecResult } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { apiErrorHandler } from "../../errors.js"; diff --git a/src/api/tests/unit/exec-batch-parallel.test.ts b/src/api/tests/unit/exec-batch-parallel.test.ts index a664525f..f03235c8 100644 --- a/src/api/tests/unit/exec-batch-parallel.test.ts +++ b/src/api/tests/unit/exec-batch-parallel.test.ts @@ -1,10 +1,10 @@ -import { InMemoryFs } from "just-bash"; import type { BashExecResult } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { executeBatch } from "../../lib/batch-exec.js"; import { readOnlyContext } from "../../read-only-context.js"; -import { SessionManager } from "../../session-manager.js"; import type { Session } from "../../session-manager.js"; +import { SessionManager } from "../../session-manager.js"; const SANDBOX_ID = "test-batch-parallel-sandbox"; diff --git a/src/api/tests/unit/exec-batch.perscript.test.ts b/src/api/tests/unit/exec-batch.perscript.test.ts index d2db7de8..a1730b1d 100644 --- a/src/api/tests/unit/exec-batch.perscript.test.ts +++ b/src/api/tests/unit/exec-batch.perscript.test.ts @@ -14,16 +14,16 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { BashExecResult, IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { apiErrorHandler } from "../../errors.js"; import { executeBatch } from "../../lib/batch-exec.js"; import { readOnlyContext } from "../../read-only-context.js"; import { execRoutes } from "../../routes/exec.js"; -import { SessionManager } from "../../session-manager.js"; import type { Session } from "../../session-manager.js"; +import { SessionManager } from "../../session-manager.js"; const AUTH_SECRET = "test-secret-for-exec-batch-perscript-at-least-32bytes!"; const secretBytes = new TextEncoder().encode(AUTH_SECRET); diff --git a/src/api/tests/unit/exec-batch.test.ts b/src/api/tests/unit/exec-batch.test.ts index 6044152f..73e2419d 100644 --- a/src/api/tests/unit/exec-batch.test.ts +++ b/src/api/tests/unit/exec-batch.test.ts @@ -1,7 +1,7 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { SandboxMeta } from "../../../sql-fs/types.js"; import { type AuthVariables, authMiddleware } from "../../auth.js"; diff --git a/src/api/tests/unit/exec-input-limit.test.ts b/src/api/tests/unit/exec-input-limit.test.ts index a557cc9e..d0811564 100644 --- a/src/api/tests/unit/exec-input-limit.test.ts +++ b/src/api/tests/unit/exec-input-limit.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest"; import { SqlFs } from "../../../sql-fs/sql-fs.js"; import type { SqlDialect } from "../../../sql-fs/types.js"; import { clientSafeErrorCode, clientSafeErrorMessage, isRetryableError, mapFsErrorToStatus } from "../../errors.js"; -import { type ExecContext, consumeExecInput, execContext } from "../../exec-context.js"; +import { consumeExecInput, type ExecContext, execContext } from "../../exec-context.js"; function context(inputLimitBytes: number): ExecContext { return { maxFileBytes: 1024, inputLimitBytes, inputBytes: 0 }; diff --git a/src/api/tests/unit/exec-lock-config.test.ts b/src/api/tests/unit/exec-lock-config.test.ts index 2dd8a1e2..c30a7d9f 100644 --- a/src/api/tests/unit/exec-lock-config.test.ts +++ b/src/api/tests/unit/exec-lock-config.test.ts @@ -5,9 +5,9 @@ import { afterEach, describe, expect, it } from "vitest"; import { + assertAcquireTimeoutAboveLeases, DEFAULT_ACQUIRE_TIMEOUT_MS, type ExecLockOptions, - assertAcquireTimeoutAboveLeases, loadExecLockOptions, } from "../../exec-lock-config.js"; diff --git a/src/api/tests/unit/exec-sse-finalization.test.ts b/src/api/tests/unit/exec-sse-finalization.test.ts index 62b128ea..552a4599 100644 --- a/src/api/tests/unit/exec-sse-finalization.test.ts +++ b/src/api/tests/unit/exec-sse-finalization.test.ts @@ -5,7 +5,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { execRoutes } from "../../routes/exec.js"; import { SessionManager } from "../../session-manager.js"; -import { FakeRedis, asRedis } from "./helpers/session-manager-fakes.js"; +import { asRedis, FakeRedis } from "./helpers/session-manager-fakes.js"; class CoherentMemoryFs extends InMemoryFs { dirty = false; diff --git a/src/api/tests/unit/exec-sync-disconnect.test.ts b/src/api/tests/unit/exec-sync-disconnect.test.ts index eac60667..a567a943 100644 --- a/src/api/tests/unit/exec-sync-disconnect.test.ts +++ b/src/api/tests/unit/exec-sync-disconnect.test.ts @@ -8,8 +8,8 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { execRoutes } from "../../routes/exec.js"; diff --git a/src/api/tests/unit/exec.test.ts b/src/api/tests/unit/exec.test.ts index e95e42fe..89b5acb9 100644 --- a/src/api/tests/unit/exec.test.ts +++ b/src/api/tests/unit/exec.test.ts @@ -7,8 +7,8 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { SandboxMeta } from "../../../sql-fs/types.js"; import { type AuthVariables, authMiddleware } from "../../auth.js"; diff --git a/src/api/tests/unit/file-ops.edit.test.ts b/src/api/tests/unit/file-ops.edit.test.ts index a9ee6930..31588a1a 100644 --- a/src/api/tests/unit/file-ops.edit.test.ts +++ b/src/api/tests/unit/file-ops.edit.test.ts @@ -6,7 +6,7 @@ import { InMemoryFs } from "just-bash"; import { describe, expect, it } from "vitest"; -import { REPLACE_FLUSH_PIECES, editFile } from "../../lib/file-ops.js"; +import { editFile, REPLACE_FLUSH_PIECES } from "../../lib/file-ops.js"; import type { Session } from "../../session-manager.js"; const MAX = 1024; diff --git a/src/api/tests/unit/files.edit.test.ts b/src/api/tests/unit/files.edit.test.ts index 97ce02de..abc5c69c 100644 --- a/src/api/tests/unit/files.edit.test.ts +++ b/src/api/tests/unit/files.edit.test.ts @@ -8,8 +8,8 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { fileRoutes } from "../../routes/files.js"; diff --git a/src/api/tests/unit/files.read-lock.test.ts b/src/api/tests/unit/files.read-lock.test.ts index 239fd1e7..970dd075 100644 --- a/src/api/tests/unit/files.read-lock.test.ts +++ b/src/api/tests/unit/files.read-lock.test.ts @@ -6,8 +6,8 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type AuthVariables, authMiddleware } from "../../auth.js"; import { fileRoutes } from "../../routes/files.js"; diff --git a/src/api/tests/unit/files.test.ts b/src/api/tests/unit/files.test.ts index 7bc81265..b2603342 100644 --- a/src/api/tests/unit/files.test.ts +++ b/src/api/tests/unit/files.test.ts @@ -11,8 +11,8 @@ import { Hono } from "hono"; import type { ContentfulStatusCode } from "hono/utils/http-status"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { SandboxMeta } from "../../../sql-fs/types.js"; import { type AuthVariables, authMiddleware } from "../../auth.js"; diff --git a/src/api/tests/unit/git-clone-cleanup.test.ts b/src/api/tests/unit/git-clone-cleanup.test.ts index fbbeba75..c259ed5a 100644 --- a/src/api/tests/unit/git-clone-cleanup.test.ts +++ b/src/api/tests/unit/git-clone-cleanup.test.ts @@ -11,8 +11,8 @@ * `symlink()`, or just-git refusing a symlink whose target escapes the worktree). */ -import { Bash, InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { Bash, InMemoryFs } from "just-bash"; import { type Auth, createServer } from "just-git/server"; import { beforeEach, describe, expect, it } from "vitest"; import { createGitCommand } from "../../commands/git-command.js"; diff --git a/src/api/tests/unit/git-command.mode-errors.test.ts b/src/api/tests/unit/git-command.mode-errors.test.ts index 85095487..7795fe3b 100644 --- a/src/api/tests/unit/git-command.mode-errors.test.ts +++ b/src/api/tests/unit/git-command.mode-errors.test.ts @@ -1,5 +1,5 @@ -import { InMemoryFs, createCommandContext } from "just-bash"; import type { ExecResult } from "just-bash"; +import { createCommandContext, InMemoryFs } from "just-bash"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { createGitCommand } from "../../commands/git-command.js"; diff --git a/src/api/tests/unit/git-command.test.ts b/src/api/tests/unit/git-command.test.ts index 6b9f7456..e4eff9cd 100644 --- a/src/api/tests/unit/git-command.test.ts +++ b/src/api/tests/unit/git-command.test.ts @@ -1,7 +1,7 @@ import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { httpsOnlyGitFetch } from "../../commands/git-command.js"; -import { SessionManager, buildSandboxBaseEnv, deriveExecGitCredentials } from "../../session-manager.js"; +import { buildSandboxBaseEnv, deriveExecGitCredentials, SessionManager } from "../../session-manager.js"; const T = "default"; diff --git a/src/api/tests/unit/git-transport-contract.test.ts b/src/api/tests/unit/git-transport-contract.test.ts index 4b773f03..55fe9a64 100644 --- a/src/api/tests/unit/git-transport-contract.test.ts +++ b/src/api/tests/unit/git-transport-contract.test.ts @@ -7,7 +7,7 @@ * actually injects lives in `tests/integration/git-sqlfs.integration.test.ts`. */ -import { Bash, InMemoryFs, defineCommand } from "just-bash"; +import { Bash, defineCommand, InMemoryFs } from "just-bash"; import { createGit } from "just-git"; import { readCommit, resolveRef } from "just-git/repo"; import { type Auth, createServer } from "just-git/server"; diff --git a/src/api/tests/unit/ingest.test.ts b/src/api/tests/unit/ingest.test.ts index 32936278..7739d824 100644 --- a/src/api/tests/unit/ingest.test.ts +++ b/src/api/tests/unit/ingest.test.ts @@ -5,8 +5,8 @@ import { Hono } from "hono"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { ICoherentFs } from "../../../sql-fs/sql-fs.js"; import type { BulkIngestFile, SandboxMeta } from "../../../sql-fs/types.js"; diff --git a/src/api/tests/unit/ingress-response.test.ts b/src/api/tests/unit/ingress-response.test.ts index 7e88be3d..086ab71b 100644 --- a/src/api/tests/unit/ingress-response.test.ts +++ b/src/api/tests/unit/ingress-response.test.ts @@ -1,4 +1,4 @@ -import { type ClientRequest, IncomingMessage, ServerResponse, request as httpRequest } from "node:http"; +import { type ClientRequest, request as httpRequest, IncomingMessage, ServerResponse } from "node:http"; import { Socket } from "node:net"; import { serve } from "@hono/node-server"; import { Hono } from "hono"; diff --git a/src/api/tests/unit/just-bash.backport.test.ts b/src/api/tests/unit/just-bash.backport.test.ts index 821e05ce..64bd42e5 100644 --- a/src/api/tests/unit/just-bash.backport.test.ts +++ b/src/api/tests/unit/just-bash.backport.test.ts @@ -1,5 +1,5 @@ import { createHash } from "node:crypto"; -import { Bash, InMemoryFs, defineCommand } from "just-bash"; +import { Bash, defineCommand, InMemoryFs } from "just-bash"; import { describe, expect, it } from "vitest"; const hash = (content: string) => createHash("sha256").update(content).digest("hex"); @@ -29,6 +29,7 @@ describe("installed just-bash text backport", () => { it.each([ ["export PROJECT_VAR=outer; sh -c 'printf %s \"$PROJECT_VAR\"'", "outer"], + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. ["UNEXPORTED=secret; sh -c 'printf %s \"${UNEXPORTED-unset}\"'", "unset"], ["sh -c 'printf %s \"$HOST_FLAG\"'", "session"], ])("retains nested shell environment behavior for %s", async (script, stdout) => { diff --git a/src/api/tests/unit/just-bash.javascript-bridge.test.ts b/src/api/tests/unit/just-bash.javascript-bridge.test.ts index 1fc1df2d..a5a796ee 100644 --- a/src/api/tests/unit/just-bash.javascript-bridge.test.ts +++ b/src/api/tests/unit/just-bash.javascript-bridge.test.ts @@ -4,44 +4,42 @@ import { describe, expect, it } from "vitest"; const MIB = 1024 * 1024; describe("installed just-bash JavaScript bridge", () => { - it( - "reads 16 MiB of binary data across chunk boundaries within the unchanged guest heap", - { timeout: 60000 }, - async () => { - const size = 16 * MIB; - const data = Buffer.alloc(size, 0x5a); - const positions = [0, size - 1]; - for (let boundary = MIB; boundary < size; boundary += MIB) positions.push(boundary - 1, boundary); - const expected = positions.map((position, index) => { - data[position] = index; - return index; - }); - const fs = new InMemoryFs({ "/large.bin": data }); - const originalRead = fs.readFileBuffer.bind(fs); - const reads: string[] = []; - fs.readFileBuffer = async (path) => { - reads.push(path); - return originalRead(path); - }; - const bash = new Bash({ - fs, - javascript: true, - executionLimits: { maxStringLength: 64 * MIB, maxWorkerMessageBytes: 64 * MIB }, - }); - const script = `js-exec -c 'const data=require("fs").readFileSync("/large.bin"); console.log(data.length, JSON.stringify(${JSON.stringify(positions)}.map(i=>data.readUInt8(i))))'`; - expect(await bash.exec(script)).toMatchObject({ - exitCode: 0, - stderr: "", - stdout: `${size} ${JSON.stringify(expected)}\n`, - }); - expect(reads.filter((path) => path === "/large.bin")).toHaveLength(1); - expect(await bash.exec("js-exec -c 'console.log(37)'")).toMatchObject({ - exitCode: 0, - stdout: "37\n", - stderr: "", - }); - }, - ); + it("reads 16 MiB of binary data across chunk boundaries within the unchanged guest heap", { + timeout: 60000, + }, async () => { + const size = 16 * MIB; + const data = Buffer.alloc(size, 0x5a); + const positions = [0, size - 1]; + for (let boundary = MIB; boundary < size; boundary += MIB) positions.push(boundary - 1, boundary); + const expected = positions.map((position, index) => { + data[position] = index; + return index; + }); + const fs = new InMemoryFs({ "/large.bin": data }); + const originalRead = fs.readFileBuffer.bind(fs); + const reads: string[] = []; + fs.readFileBuffer = async (path) => { + reads.push(path); + return originalRead(path); + }; + const bash = new Bash({ + fs, + javascript: true, + executionLimits: { maxStringLength: 64 * MIB, maxWorkerMessageBytes: 64 * MIB }, + }); + const script = `js-exec -c 'const data=require("fs").readFileSync("/large.bin"); console.log(data.length, JSON.stringify(${JSON.stringify(positions)}.map(i=>data.readUInt8(i))))'`; + expect(await bash.exec(script)).toMatchObject({ + exitCode: 0, + stderr: "", + stdout: `${size} ${JSON.stringify(expected)}\n`, + }); + expect(reads.filter((path) => path === "/large.bin")).toHaveLength(1); + expect(await bash.exec("js-exec -c 'console.log(37)'")).toMatchObject({ + exitCode: 0, + stdout: "37\n", + stderr: "", + }); + }); it("rejects 49 MiB before reading host content and remains reusable", { timeout: 60000 }, async () => { const fs = new InMemoryFs({ "/large.bin": Buffer.alloc(49 * MIB) }); diff --git a/src/api/tests/unit/just-bash.python-filesystem-identity.test.ts b/src/api/tests/unit/just-bash.python-filesystem-identity.test.ts index 671af250..fc4c09e5 100644 --- a/src/api/tests/unit/just-bash.python-filesystem-identity.test.ts +++ b/src/api/tests/unit/just-bash.python-filesystem-identity.test.ts @@ -1,39 +1,37 @@ import { Bash, InMemoryFs } from "just-bash"; import { expect, it } from "vitest"; -it( - "serializes real Python reads across fresh Bash command wrappers on one filesystem", - { timeout: 20000 }, - async () => { - const fs = new InMemoryFs({ "/input": "safe" }); - const originalRead = fs.readFileBuffer.bind(fs); - let reads = 0; - let releaseRead: () => void = () => {}; - const heldRead = new Promise((resolve) => { - releaseRead = resolve; - }); - fs.readFileBuffer = async (path) => { - if (path === "/input" && ++reads === 1) await heldRead; - return await originalRead(path); - }; - const shell = () => - new Bash({ fs, python: true, defenseInDepth: false, executionLimits: { maxWorkerMessageBytes: 8192 } }); - const command = "python3 -c 'print(open(\"/input\").read())'"; - const first = shell().exec(command); - let second: ReturnType | undefined; - let before: number | undefined; - try { - await expect.poll(() => reads, { timeout: 5000 }).toBe(1); - second = shell().exec(command); - await new Promise((resolve) => setTimeout(resolve, 500)); - before = reads; - } finally { - releaseRead(); - await Promise.allSettled(second === undefined ? [first] : [first, second]); - } - expect(before).toBe(1); - expect(await first).toMatchObject({ exitCode: 0, stdout: "safe\n", stderr: "" }); - expect(await second).toMatchObject({ exitCode: 0, stdout: "safe\n", stderr: "" }); - expect(reads).toBe(2); - }, -); +it("serializes real Python reads across fresh Bash command wrappers on one filesystem", { + timeout: 20000, +}, async () => { + const fs = new InMemoryFs({ "/input": "safe" }); + const originalRead = fs.readFileBuffer.bind(fs); + let reads = 0; + let releaseRead: () => void = () => {}; + const heldRead = new Promise((resolve) => { + releaseRead = resolve; + }); + fs.readFileBuffer = async (path) => { + if (path === "/input" && ++reads === 1) await heldRead; + return await originalRead(path); + }; + const shell = () => + new Bash({ fs, python: true, defenseInDepth: false, executionLimits: { maxWorkerMessageBytes: 8192 } }); + const command = "python3 -c 'print(open(\"/input\").read())'"; + const first = shell().exec(command); + let second: ReturnType | undefined; + let before: number | undefined; + try { + await expect.poll(() => reads, { timeout: 5000 }).toBe(1); + second = shell().exec(command); + await new Promise((resolve) => setTimeout(resolve, 500)); + before = reads; + } finally { + releaseRead(); + await Promise.allSettled(second === undefined ? [first] : [first, second]); + } + expect(before).toBe(1); + expect(await first).toMatchObject({ exitCode: 0, stdout: "safe\n", stderr: "" }); + expect(await second).toMatchObject({ exitCode: 0, stdout: "safe\n", stderr: "" }); + expect(reads).toBe(2); +}); diff --git a/src/api/tests/unit/lock-loss-post-commit.test.ts b/src/api/tests/unit/lock-loss-post-commit.test.ts index 09ace637..be3b75ed 100644 --- a/src/api/tests/unit/lock-loss-post-commit.test.ts +++ b/src/api/tests/unit/lock-loss-post-commit.test.ts @@ -13,7 +13,7 @@ import type { Redis } from "ioredis"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { LockLostAfterCommitError, LockLostError, execLockKey, withDistributedLock } from "../../distributed-lock.js"; +import { execLockKey, LockLostAfterCommitError, LockLostError, withDistributedLock } from "../../distributed-lock.js"; import { type RWLockKeys, rwLockKeys, withDistributedRWLock } from "../../distributed-rw-lock.js"; import { isRetryableError } from "../../errors.js"; diff --git a/src/api/tests/unit/mcp-file-edit.test.ts b/src/api/tests/unit/mcp-file-edit.test.ts index c63c3dfa..9f254efb 100644 --- a/src/api/tests/unit/mcp-file-edit.test.ts +++ b/src/api/tests/unit/mcp-file-edit.test.ts @@ -5,8 +5,8 @@ * envelope, the `ok:false` rejection codes, and that a rejection leaves the file untouched. */ -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { registerTools } from "../../mcp/tools.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/mcp-file-io.test.ts b/src/api/tests/unit/mcp-file-io.test.ts index feed43d5..d2a9173d 100644 --- a/src/api/tests/unit/mcp-file-io.test.ts +++ b/src/api/tests/unit/mcp-file-io.test.ts @@ -5,8 +5,8 @@ * envelope, paging bounds, and that non-text files are refused rather than mangled. */ -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { registerTools } from "../../mcp/tools.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/mcp-tools.test.ts b/src/api/tests/unit/mcp-tools.test.ts index c2e9072a..b9ae5010 100644 --- a/src/api/tests/unit/mcp-tools.test.ts +++ b/src/api/tests/unit/mcp-tools.test.ts @@ -4,8 +4,8 @@ */ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { InMemoryFs } from "just-bash"; import type { BashExecResult } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { registerTools } from "../../mcp/tools.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/mcp.test.ts b/src/api/tests/unit/mcp.test.ts index 9ce167de..f1aca841 100644 --- a/src/api/tests/unit/mcp.test.ts +++ b/src/api/tests/unit/mcp.test.ts @@ -14,15 +14,15 @@ import { join } from "node:path"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it } from "vitest"; import type { ICoherentFs } from "../../../sql-fs/sql-fs.js"; import type { BulkIngestFile, SandboxMeta } from "../../../sql-fs/types.js"; import { createMcpServer } from "../../mcp/server.js"; import { registerTools } from "../../mcp/tools.js"; -import { SessionManager } from "../../session-manager.js"; import type { Session } from "../../session-manager.js"; +import { SessionManager } from "../../session-manager.js"; /** * Wraps `InMemoryFs` with a `bulkIngest` shim so MCP fs_ingest tests (which diff --git a/src/api/tests/unit/rate-limit.test.ts b/src/api/tests/unit/rate-limit.test.ts index 88a77e35..4cba1a3c 100644 --- a/src/api/tests/unit/rate-limit.test.ts +++ b/src/api/tests/unit/rate-limit.test.ts @@ -4,7 +4,7 @@ import { Hono } from "hono"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { InMemoryRateLimitStore, clientIp, rateLimit } from "../../rate-limit.js"; +import { clientIp, InMemoryRateLimitStore, rateLimit } from "../../rate-limit.js"; describe("InMemoryRateLimitStore", () => { it("allows up to max in window then denies", () => { diff --git a/src/api/tests/unit/sandbox-id-validation.test.ts b/src/api/tests/unit/sandbox-id-validation.test.ts index c82bcb89..b00b77d0 100644 Binary files a/src/api/tests/unit/sandbox-id-validation.test.ts and b/src/api/tests/unit/sandbox-id-validation.test.ts differ diff --git a/src/api/tests/unit/sandboxes.test.ts b/src/api/tests/unit/sandboxes.test.ts index 507002ff..eae9988c 100644 --- a/src/api/tests/unit/sandboxes.test.ts +++ b/src/api/tests/unit/sandboxes.test.ts @@ -5,8 +5,8 @@ import { Hono } from "hono"; import { bodyLimit } from "hono/body-limit"; import { SignJWT } from "jose"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { SandboxMeta } from "../../../sql-fs/types.js"; import { type AuthVariables, authMiddleware } from "../../auth.js"; diff --git a/src/api/tests/unit/session-manager.cross-replica.test.ts b/src/api/tests/unit/session-manager.cross-replica.test.ts index 34d74ee6..a5bc4d80 100644 --- a/src/api/tests/unit/session-manager.cross-replica.test.ts +++ b/src/api/tests/unit/session-manager.cross-replica.test.ts @@ -15,8 +15,8 @@ */ import type { Redis } from "ioredis"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/session-manager.cwd.test.ts b/src/api/tests/unit/session-manager.cwd.test.ts index 5720d6bb..31f2da73 100644 --- a/src/api/tests/unit/session-manager.cwd.test.ts +++ b/src/api/tests/unit/session-manager.cwd.test.ts @@ -8,8 +8,8 @@ * `session.cwd`, then passing it as `opts.cwd` before the next exec. */ -import { Bash, InMemoryFs } from "just-bash"; import type { BashExecResult } from "just-bash"; +import { Bash, InMemoryFs } from "just-bash"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/session-manager.ecoherence-contract.test.ts b/src/api/tests/unit/session-manager.ecoherence-contract.test.ts index 85a8d346..6be7ccd8 100644 --- a/src/api/tests/unit/session-manager.ecoherence-contract.test.ts +++ b/src/api/tests/unit/session-manager.ecoherence-contract.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from "vitest"; import { SessionManager } from "../../session-manager.js"; -import { FakeRedis, StubCoherentFs, asRedis, makeFsFactory } from "./helpers/session-manager-fakes.js"; +import { asRedis, FakeRedis, makeFsFactory, StubCoherentFs } from "./helpers/session-manager-fakes.js"; describe("SessionManager recovery contract", () => { it("commits once without touching legacy Redis publication", async () => { diff --git a/src/api/tests/unit/session-manager.exec-lock.test.ts b/src/api/tests/unit/session-manager.exec-lock.test.ts index bc776f33..db5cb70d 100644 --- a/src/api/tests/unit/session-manager.exec-lock.test.ts +++ b/src/api/tests/unit/session-manager.exec-lock.test.ts @@ -13,8 +13,8 @@ */ import type { Redis } from "ioredis"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { rwLockKeys } from "../../distributed-rw-lock.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/session-manager.f2-lease-loss-abort.test.ts b/src/api/tests/unit/session-manager.f2-lease-loss-abort.test.ts index 710436e7..35553903 100644 --- a/src/api/tests/unit/session-manager.f2-lease-loss-abort.test.ts +++ b/src/api/tests/unit/session-manager.f2-lease-loss-abort.test.ts @@ -1,6 +1,6 @@ import type { Redis } from "ioredis"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it } from "vitest"; import { rwLockKeys } from "../../distributed-rw-lock.js"; import { sessionLeaseSignal } from "../../session-lease-context.js"; diff --git a/src/api/tests/unit/session-manager.f4-rwlock-reader-lock.test.ts b/src/api/tests/unit/session-manager.f4-rwlock-reader-lock.test.ts index d8b9655e..51214757 100644 --- a/src/api/tests/unit/session-manager.f4-rwlock-reader-lock.test.ts +++ b/src/api/tests/unit/session-manager.f4-rwlock-reader-lock.test.ts @@ -13,8 +13,8 @@ */ import type { Redis } from "ioredis"; -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { SqlFs } from "../../../sql-fs/sql-fs.js"; import type { PathCacheEntry, SqlDialect } from "../../../sql-fs/types.js"; diff --git a/src/api/tests/unit/session-manager.lifecycle.test.ts b/src/api/tests/unit/session-manager.lifecycle.test.ts index 51515782..77192f88 100644 --- a/src/api/tests/unit/session-manager.lifecycle.test.ts +++ b/src/api/tests/unit/session-manager.lifecycle.test.ts @@ -6,8 +6,8 @@ * - runtime semaphore waiters are removed on abort */ -import { InMemoryFs, defineCommand } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { defineCommand, InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { RuntimeBackpressureError, SessionManager } from "../../session-manager.js"; import type { OwnerMetadata } from "../../worker-owner/protocol.js"; diff --git a/src/api/tests/unit/session-manager.read-only.test.ts b/src/api/tests/unit/session-manager.read-only.test.ts index efbcacba..246f182f 100644 --- a/src/api/tests/unit/session-manager.read-only.test.ts +++ b/src/api/tests/unit/session-manager.read-only.test.ts @@ -11,8 +11,8 @@ * GET, one reload). */ -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { describe, expect, it, vi } from "vitest"; import { readOnlyContext } from "../../read-only-context.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/session-manager.rehydrate.test.ts b/src/api/tests/unit/session-manager.rehydrate.test.ts index fc066321..c4995d21 100644 --- a/src/api/tests/unit/session-manager.rehydrate.test.ts +++ b/src/api/tests/unit/session-manager.rehydrate.test.ts @@ -6,8 +6,9 @@ * 2. Cold hit: sandbox in PG but not in pool -> rehydrate via getOrCreate * 3. Cold miss: sandbox not in PG -> throw ENOENT */ -import { InMemoryFs } from "just-bash"; + import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { beforeEach, describe, expect, it, vi } from "vitest"; import type { SandboxMeta } from "../../../sql-fs/types.js"; import { SessionManager } from "../../session-manager.js"; diff --git a/src/api/tests/unit/session-manager.test.ts b/src/api/tests/unit/session-manager.test.ts index 0c936786..2292d005 100644 --- a/src/api/tests/unit/session-manager.test.ts +++ b/src/api/tests/unit/session-manager.test.ts @@ -2,8 +2,8 @@ * Unit tests for SessionManager — US-074, US-075, US-076 */ -import { InMemoryFs } from "just-bash"; import type { IFileSystem } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { SessionManager } from "../../session-manager.js"; @@ -386,8 +386,11 @@ describe("SessionManager runtime options + Python semaphore (US-080a)", () => { }); await Promise.all([ + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=py; command=${command}thon3; $command -c 'print(1)'"), + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=py; command=${command}thon3; $command -c 'print(2)'"), + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=py; command=${command}thon3; $command -c 'print(3)'"), ]); expect(peak).toBe(1); @@ -489,8 +492,11 @@ describe("SessionManager JavaScript semaphore (MAX_CONCURRENT_JS)", () => { }); await Promise.all([ + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=no; command=${command}de; $command -e 'console.log(1)'"), + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=no; command=${command}de; $command -e 'console.log(2)'"), + // biome-ignore lint/suspicious/noTemplateCurlyInString: Bash expands this literal. sm.execWithRuntimeThrottle(session, "command=no; command=${command}de; $command -e 'console.log(3)'"), ]); expect(peak).toBe(1); diff --git a/src/api/tests/unit/session-runtime.scope.test.ts b/src/api/tests/unit/session-runtime.scope.test.ts index ad27b1a4..53e24206 100644 --- a/src/api/tests/unit/session-runtime.scope.test.ts +++ b/src/api/tests/unit/session-runtime.scope.test.ts @@ -1,5 +1,5 @@ -import { InMemoryFs } from "just-bash"; import type { BashExecResult } from "just-bash"; +import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { ownerCancellation } from "../../../execution/owner-cancellation.js"; import { SqlFs } from "../../../sql-fs/sql-fs.js"; diff --git a/src/api/tests/unit/test-app-error-shape.test.ts b/src/api/tests/unit/test-app-error-shape.test.ts index 5aae274e..5c450848 100644 --- a/src/api/tests/unit/test-app-error-shape.test.ts +++ b/src/api/tests/unit/test-app-error-shape.test.ts @@ -5,7 +5,7 @@ * own handler again. */ -import { readFileSync, readdirSync } from "node:fs"; +import { readdirSync, readFileSync } from "node:fs"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import { Hono } from "hono"; diff --git a/src/api/tests/unit/worker-pool-pressure.test.ts b/src/api/tests/unit/worker-pool-pressure.test.ts index 3ff9951e..9fbf78da 100644 --- a/src/api/tests/unit/worker-pool-pressure.test.ts +++ b/src/api/tests/unit/worker-pool-pressure.test.ts @@ -1,7 +1,7 @@ import { AsyncLocalStorage } from "node:async_hooks"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; -import { MockOwnerWorker, latestMockWorker } from "../fixtures/mock-owner-worker.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; +import { latestMockWorker, MockOwnerWorker } from "../fixtures/mock-owner-worker.js"; vi.mock("node:worker_threads", async () => { const { MockOwnerWorker } = await import("../fixtures/mock-owner-worker.js"); diff --git a/src/api/tests/unit/worker-protocol.test.ts b/src/api/tests/unit/worker-protocol.test.ts index 56e90739..54f3d52a 100644 --- a/src/api/tests/unit/worker-protocol.test.ts +++ b/src/api/tests/unit/worker-protocol.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { type OwnerCommand, type OwnerIdentity, mayApply } from "../../worker-owner/protocol.js"; +import { mayApply, type OwnerCommand, type OwnerIdentity } from "../../worker-owner/protocol.js"; const identity: OwnerIdentity = { tenantId: "tenant", diff --git a/src/api/tests/unit/worker-request-outcome.test.ts b/src/api/tests/unit/worker-request-outcome.test.ts index 4d76470d..e98ff6e4 100644 --- a/src/api/tests/unit/worker-request-outcome.test.ts +++ b/src/api/tests/unit/worker-request-outcome.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { retirePostgresSandboxGeneration } from "../../../sql-fs/index.js"; import { readOnlyContext } from "../../read-only-context.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import { OutcomeUnknownError, type OwnerCommand, type OwnerIdentity } from "../../worker-owner/protocol.js"; -import { MockOwnerWorker, latestMockWorker } from "../fixtures/mock-owner-worker.js"; +import { latestMockWorker, MockOwnerWorker } from "../fixtures/mock-owner-worker.js"; vi.mock("node:worker_threads", async () => { const { MockOwnerWorker } = await import("../fixtures/mock-owner-worker.js"); diff --git a/src/api/tests/unit/worker-resource-policy.test.ts b/src/api/tests/unit/worker-resource-policy.test.ts index acc874d9..6411473f 100644 --- a/src/api/tests/unit/worker-resource-policy.test.ts +++ b/src/api/tests/unit/worker-resource-policy.test.ts @@ -2,7 +2,7 @@ import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { createSessionRuntime } from "../../session-runtime/engine.js"; import { budgetWorkerReply } from "../../worker-owner/message-budget.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import type { OwnerReply } from "../../worker-owner/protocol.js"; const cpuProbe = vi.hoisted(() => ({ diff --git a/src/api/tests/unit/worker-runtime-reply-budget.test.ts b/src/api/tests/unit/worker-runtime-reply-budget.test.ts index a304714a..91d9112c 100644 --- a/src/api/tests/unit/worker-runtime-reply-budget.test.ts +++ b/src/api/tests/unit/worker-runtime-reply-budget.test.ts @@ -3,8 +3,8 @@ import { MessageChannel, Worker } from "node:worker_threads"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { SessionScriptScope } from "../../session-runtime/engine.js"; import { assertWorkerMessageBudget } from "../../worker-owner/message-budget.js"; -import { mayApply } from "../../worker-owner/protocol.js"; import type { OwnerCommand, OwnerReply, OwnerRequest } from "../../worker-owner/protocol.js"; +import { mayApply } from "../../worker-owner/protocol.js"; const channels: MessageChannel[] = []; afterEach(() => { diff --git a/src/api/tests/unit/worker-script-scope.test.ts b/src/api/tests/unit/worker-script-scope.test.ts index 272495d1..4e2bcfaf 100644 --- a/src/api/tests/unit/worker-script-scope.test.ts +++ b/src/api/tests/unit/worker-script-scope.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { WorkerFileSystem, WorkerScriptScope } from "../../worker-owner/filesystem.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; const pools: WorkerOwnerPool[] = []; diff --git a/src/api/tests/unit/worker-tenant-admission.test.ts b/src/api/tests/unit/worker-tenant-admission.test.ts index 5d18ceb9..bc6606c1 100644 --- a/src/api/tests/unit/worker-tenant-admission.test.ts +++ b/src/api/tests/unit/worker-tenant-admission.test.ts @@ -2,7 +2,7 @@ import { InMemoryFs } from "just-bash"; import { afterEach, describe, expect, it, vi } from "vitest"; import { SessionManager } from "../../session-manager.js"; import { FairAdmission } from "../../worker-owner/admission.js"; -import { WorkerOwnerPool, loadWorkerPoolOptions } from "../../worker-owner/pool.js"; +import { loadWorkerPoolOptions, WorkerOwnerPool } from "../../worker-owner/pool.js"; import { workerRequestContext } from "../../worker-owner/request-context.js"; function checkpoint() { diff --git a/src/api/worker-owner/filesystem.ts b/src/api/worker-owner/filesystem.ts index bb349f47..71be264d 100644 --- a/src/api/worker-owner/filesystem.ts +++ b/src/api/worker-owner/filesystem.ts @@ -1,6 +1,6 @@ import path from "node:path"; import type { IFileSystem } from "just-bash"; -import { type ScriptScope, runInScriptScope } from "../../sql-fs/script-scope.js"; +import { runInScriptScope, type ScriptScope } from "../../sql-fs/script-scope.js"; import type { ICoherentFs } from "../../sql-fs/sql-fs.js"; import type { BulkIngestFile } from "../../sql-fs/types.js"; import type { WorkerOwnerPool } from "./pool.js"; diff --git a/src/api/worker-owner/message-budget.ts b/src/api/worker-owner/message-budget.ts index 1363fee9..ff718718 100644 --- a/src/api/worker-owner/message-budget.ts +++ b/src/api/worker-owner/message-budget.ts @@ -1,4 +1,4 @@ -import { OutcomeUnknownError, type OwnerCommand, type OwnerReply, mayApply } from "./protocol.js"; +import { mayApply, OutcomeUnknownError, type OwnerCommand, type OwnerReply } from "./protocol.js"; export function assertWorkerMessageBudget(value: unknown, maxBytes: number, additionalBytes = 0): void { let bytes = additionalBytes; diff --git a/src/api/worker-owner/pool.ts b/src/api/worker-owner/pool.ts index 06ca741e..59d4e536 100644 --- a/src/api/worker-owner/pool.ts +++ b/src/api/worker-owner/pool.ts @@ -9,6 +9,7 @@ import { readOnlyContext } from "../read-only-context.js"; import { FairAdmission } from "./admission.js"; import { assertWorkerMessageBudget } from "./message-budget.js"; import { + mayApply, OutcomeUnknownError, type OwnerCommand, type OwnerCommandKind, @@ -19,7 +20,6 @@ import { type OwnerRequest, type OwnerResult, type ShellExecutionLimits, - mayApply, } from "./protocol.js"; import { workerRequestContext } from "./request-context.js"; import { RequestOutcome, workerFailureCode } from "./request-outcome.js"; diff --git a/src/api/worker-owner/request-outcome.ts b/src/api/worker-owner/request-outcome.ts index f0a44f67..2ce74d05 100644 --- a/src/api/worker-owner/request-outcome.ts +++ b/src/api/worker-owner/request-outcome.ts @@ -1,5 +1,5 @@ import { preservesAmbiguousOutcome } from "../errors.js"; -import { OutcomeUnknownError, type OwnerCommand, type OwnerCommandKind, mayApply } from "./protocol.js"; +import { mayApply, OutcomeUnknownError, type OwnerCommand, type OwnerCommandKind } from "./protocol.js"; export function workerFailureCode(error: unknown): string | undefined { return error !== null && typeof error === "object" && "code" in error && typeof error.code === "string" diff --git a/src/api/worker-owner/runtime.ts b/src/api/worker-owner/runtime.ts index 0e6bb42c..4c698d61 100644 --- a/src/api/worker-owner/runtime.ts +++ b/src/api/worker-owner/runtime.ts @@ -9,10 +9,10 @@ import type { ICoherentFs } from "../../sql-fs/sql-fs.js"; import { LockLostError } from "../distributed-lock.js"; import { readOnlyContext } from "../read-only-context.js"; import { - type SessionRuntime, closeSessionRuntime, createSessionRuntime, executeSessionRuntime, + type SessionRuntime, } from "../session-runtime/engine.js"; import { budgetWorkerReply } from "./message-budget.js"; import type { WorkerPoolOptions } from "./pool.js"; diff --git a/src/redis/tests/circuit-breaker.role.test.ts b/src/redis/tests/circuit-breaker.role.test.ts index 2b43e731..218b5b41 100644 --- a/src/redis/tests/circuit-breaker.role.test.ts +++ b/src/redis/tests/circuit-breaker.role.test.ts @@ -6,9 +6,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { + getRedisCircuitBreaker, type ProbeTicketHolder, RedisCircuitBreaker, - getRedisCircuitBreaker, resetRedisCircuitBreakerForTest, } from "../circuit-breaker.js"; diff --git a/src/sql-fs/index.ts b/src/sql-fs/index.ts index a98bbeaf..a8d081f1 100644 --- a/src/sql-fs/index.ts +++ b/src/sql-fs/index.ts @@ -21,7 +21,7 @@ import { PostgresDialect } from "./dialects/postgres.js"; import { raceDriverFault } from "./driver-fault.js"; import { createEnoent } from "./errors.js"; import { RedisBlobCache } from "./redis-blob-cache.js"; -import { type ScriptTxBufferConfig, loadScriptTxBufferConfig } from "./script-tx-buffer.js"; +import { loadScriptTxBufferConfig, type ScriptTxBufferConfig } from "./script-tx-buffer.js"; import { SqlFs } from "./sql-fs.js"; import type { StorageBackend } from "./types.js"; diff --git a/src/sql-fs/session-scoped-fs.ts b/src/sql-fs/session-scoped-fs.ts index 5523c298..1d779b07 100644 --- a/src/sql-fs/session-scoped-fs.ts +++ b/src/sql-fs/session-scoped-fs.ts @@ -1,4 +1,4 @@ -import { type ScriptScope, runInScriptScope } from "./script-scope.js"; +import { runInScriptScope, type ScriptScope } from "./script-scope.js"; import type { IScriptTxFs } from "./sql-fs.js"; export class SessionScopedFs implements ScriptScope { diff --git a/src/sql-fs/sql-fs.ts b/src/sql-fs/sql-fs.ts index d6a7a4d8..b033b17b 100644 --- a/src/sql-fs/sql-fs.ts +++ b/src/sql-fs/sql-fs.ts @@ -146,7 +146,7 @@ export interface IReadOnlyScopeFs extends IFileSystem { import { CoherentView } from "./state/coherent-view.js"; import { NamespaceOperations } from "./state/namespace-operations.js"; -import { DEV_NULL, assertStoredPath, nameOf, normalizeFsPath, validatePath } from "./state/paths.js"; +import { assertStoredPath, DEV_NULL, nameOf, normalizeFsPath, validatePath } from "./state/paths.js"; import { ScriptPersistence } from "./state/script-persistence.js"; export class SqlFs implements ICoherentFs, IReadOnlyScopeFs { readonly #dialect: SqlDialect; diff --git a/src/sql-fs/state/coherent-view.ts b/src/sql-fs/state/coherent-view.ts index 4f101828..c8f9447d 100644 --- a/src/sql-fs/state/coherent-view.ts +++ b/src/sql-fs/state/coherent-view.ts @@ -2,9 +2,10 @@ import type { LRUCache } from "lru-cache"; import { createEloop, createEnoent, createEnotdir, createEsandboxgone } from "../errors.js"; import { INODE_KIND, type PathCacheEntry, type SandboxGeneration, type SqlDialect } from "../types.js"; import { FileContents } from "./file-contents.js"; -import { DEV_NULL, assertStoredPath, nameOf, parentOf, resolvePath, validatePath } from "./paths.js"; +import { assertStoredPath, DEV_NULL, nameOf, parentOf, resolvePath, validatePath } from "./paths.js"; import type { ScriptPersistence } from "./script-persistence.js"; import type { ContentChange, PathChange, Publication, ScopeSettlement } from "./types.js"; + interface CommittedView { epoch: bigint; readonly entries: Map; diff --git a/src/sql-fs/state/namespace-operations.ts b/src/sql-fs/state/namespace-operations.ts index 391c4be6..ae56b676 100644 --- a/src/sql-fs/state/namespace-operations.ts +++ b/src/sql-fs/state/namespace-operations.ts @@ -9,6 +9,7 @@ import * as links from "./namespace/links-moves.js"; import { DEV_NULL, parentOf } from "./paths.js"; import type { ScriptPersistence } from "./script-persistence.js"; import type { NamespacePolicy } from "./types.js"; + type CreateExclusiveOpts = Parameters>[1]; type NamespaceDialect = fileWrites.FileWriteQueries & tree.TreeQueries & diff --git a/src/sql-fs/state/namespace/directory-tree.ts b/src/sql-fs/state/namespace/directory-tree.ts index f836f870..bfc28d95 100644 --- a/src/sql-fs/state/namespace/directory-tree.ts +++ b/src/sql-fs/state/namespace/directory-tree.ts @@ -2,9 +2,9 @@ import type { CpOptions, MkdirOptions, RmOptions } from "just-bash"; import { createEexist, createEisdir, createEnoent, createEnotdir, createEnotempty } from "../../errors.js"; import { INODE_KIND, type SqlDialect } from "../../types.js"; import type { CoherentView } from "../coherent-view.js"; -import { DEV_NULL, assertStoredPath, nameOf, parentOf, validatePath } from "../paths.js"; +import { assertStoredPath, DEV_NULL, nameOf, parentOf, validatePath } from "../paths.js"; import type { ScriptPersistence } from "../script-persistence.js"; -import { type ContentChange, type NamespacePolicy, PER_MUTATION_BASE_BYTES, type PathChange } from "../types.js"; +import { type ContentChange, type NamespacePolicy, type PathChange, PER_MUTATION_BASE_BYTES } from "../types.js"; const DEV_NULL_STAT = { mode: 0o666 }; export type TreeQueries = Pick< diff --git a/src/sql-fs/state/namespace/file-writes.ts b/src/sql-fs/state/namespace/file-writes.ts index 8b99b98d..753c3fa9 100644 --- a/src/sql-fs/state/namespace/file-writes.ts +++ b/src/sql-fs/state/namespace/file-writes.ts @@ -8,8 +8,8 @@ import { type ContentChange, type MutationSpec, type NamespacePolicy, - PER_MUTATION_BASE_BYTES, type PathChange, + PER_MUTATION_BASE_BYTES, } from "../types.js"; const NEW_FILE_MODE = 0o644; diff --git a/src/sql-fs/state/namespace/links-moves.ts b/src/sql-fs/state/namespace/links-moves.ts index c60f22b2..3da2c108 100644 --- a/src/sql-fs/state/namespace/links-moves.ts +++ b/src/sql-fs/state/namespace/links-moves.ts @@ -11,7 +11,7 @@ import { INODE_KIND, type PathCacheEntry, type SqlDialect } from "../../types.js import type { CoherentView } from "../coherent-view.js"; import { assertStoredPath, nameOf, parentOf, validatePath } from "../paths.js"; import type { ScriptPersistence } from "../script-persistence.js"; -import { type ContentChange, type NamespacePolicy, PER_MUTATION_BASE_BYTES, type PathChange } from "../types.js"; +import { type ContentChange, type NamespacePolicy, type PathChange, PER_MUTATION_BASE_BYTES } from "../types.js"; export type LinkMoveQueries = Pick< SqlDialect, diff --git a/src/sql-fs/tests/unit/sql-fs.content-cache.test.ts b/src/sql-fs/tests/unit/sql-fs.content-cache.test.ts index 1d30a1df..d23e67ff 100644 --- a/src/sql-fs/tests/unit/sql-fs.content-cache.test.ts +++ b/src/sql-fs/tests/unit/sql-fs.content-cache.test.ts @@ -9,8 +9,8 @@ import { describe, expect, it, vi } from "vitest"; import { SqlFs } from "../../sql-fs.js"; -import { INODE_KIND } from "../../types.js"; import type { PathCacheEntry, SqlDialect } from "../../types.js"; +import { INODE_KIND } from "../../types.js"; // ── Helpers ───────────────────────────────────────────────────────────────────