From 6180ca9f2d652ed87d04e251ee1e9cb58a58b949 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:18:27 +0100 Subject: [PATCH 01/12] feat: add @plainbrew/next-basic-auth-proxy package Basic Auth handler for Next.js proxy.ts. Reads credentials from BASIC_AUTH_USER/PASSWORD env vars and controls Vercel environments via BASIC_AUTH_TARGET (all | production). Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/.gitignore | 1 + packages/next-basic-auth-proxy/package.json | 39 + packages/next-basic-auth-proxy/src/index.ts | 61 ++ packages/next-basic-auth-proxy/tsconfig.json | 14 + packages/next-basic-auth-proxy/tsup.config.ts | 8 + pnpm-lock.yaml | 916 ++++++++++++++++++ pnpm-workspace.yaml | 2 + 7 files changed, 1041 insertions(+) create mode 100644 packages/next-basic-auth-proxy/.gitignore create mode 100644 packages/next-basic-auth-proxy/package.json create mode 100644 packages/next-basic-auth-proxy/src/index.ts create mode 100644 packages/next-basic-auth-proxy/tsconfig.json create mode 100644 packages/next-basic-auth-proxy/tsup.config.ts create mode 100644 pnpm-workspace.yaml diff --git a/packages/next-basic-auth-proxy/.gitignore b/packages/next-basic-auth-proxy/.gitignore new file mode 100644 index 0000000..849ddff --- /dev/null +++ b/packages/next-basic-auth-proxy/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/packages/next-basic-auth-proxy/package.json b/packages/next-basic-auth-proxy/package.json new file mode 100644 index 0000000..074faf3 --- /dev/null +++ b/packages/next-basic-auth-proxy/package.json @@ -0,0 +1,39 @@ +{ + "name": "@plainbrew/next-basic-auth-proxy", + "version": "0.0.0", + "description": "Basic Auth handler for Next.js proxy.ts", + "keywords": [ + "basic-auth", + "middleware", + "next.js", + "proxy" + ], + "license": "MIT", + "files": [ + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "scripts": { + "build": "tsup", + "dev": "tsup --watch" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "tsup": "^8.0.0", + "typescript": "^5.0.0" + } +} diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts new file mode 100644 index 0000000..8cad9d8 --- /dev/null +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -0,0 +1,61 @@ +/* eslint-disable n/no-process-env */ + +export function basicAuth(request: Request): Response | null { + function unauthorized() { + return new Response("Auth required", { + status: 401, + headers: { + "WWW-Authenticate": "Basic", + }, + }); + } + + // Vercel 環境でない場合は認証不要 + if (process.env.VERCEL !== "1") { + return null; + } + + // BASIC_AUTH_TARGET のバリデーション + if ( + !process.env.BASIC_AUTH_TARGET || + !["all", "production"].includes(process.env.BASIC_AUTH_TARGET) + ) { + throw new Error("BASIC_AUTH_TARGET must be 'all' or 'production'"); + } + + // production ターゲットでも、production 環境以外では認証スキップ + if (process.env.BASIC_AUTH_TARGET === "production" && process.env.VERCEL_ENV !== "production") { + return null; + } + + const authUser = process.env.BASIC_AUTH_USER; + if (!authUser) { + throw new Error("BASIC_AUTH_USER is not set"); + } + + const authPassword = process.env.BASIC_AUTH_PASSWORD; + if (!authPassword) { + throw new Error("BASIC_AUTH_PASSWORD is not set"); + } + + const authorization = request.headers.get("authorization"); + if (!authorization) { + return unauthorized(); + } + + const authValue = authorization.split(" ")[1]; + if (authValue === undefined) { + return unauthorized(); + } + + try { + const [user, password] = atob(authValue).split(":"); + if (user !== authUser || password !== authPassword) { + return unauthorized(); + } + } catch { + return unauthorized(); + } + + return null; +} diff --git a/packages/next-basic-auth-proxy/tsconfig.json b/packages/next-basic-auth-proxy/tsconfig.json new file mode 100644 index 0000000..a8e64cf --- /dev/null +++ b/packages/next-basic-auth-proxy/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2019", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2019", "DOM"], + "strict": true, + "declaration": true, + "esModuleInterop": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": ["src"] +} diff --git a/packages/next-basic-auth-proxy/tsup.config.ts b/packages/next-basic-auth-proxy/tsup.config.ts new file mode 100644 index 0000000..15936c6 --- /dev/null +++ b/packages/next-basic-auth-proxy/tsup.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["cjs", "esm"], + dts: true, + clean: true, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5f6e84..bc4c1dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,189 @@ importers: specifier: ^0.36.0 version: 0.36.0 + packages/next-basic-auth-proxy: + devDependencies: + '@types/node': + specifier: ^22.0.0 + version: 22.19.13 + tsup: + specifier: ^8.0.0 + version: 8.5.1(typescript@5.9.3)(yaml@2.8.2) + typescript: + specifier: ^5.0.0 + version: 5.9.3 + packages: + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@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/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@oxfmt/binding-android-arm-eabi@0.36.0': resolution: {integrity: sha512-Z4yVHJWx/swHHjtr0dXrBZb6LxS+qNz1qdza222mWwPTUK4L790+5i3LTgjx3KYGBzcYpjaiZBw4vOx94dH7MQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -142,6 +323,155 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@22.19.13': + resolution: {integrity: sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + ansi-escapes@7.3.0: resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} @@ -154,10 +484,27 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -173,6 +520,26 @@ packages: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -180,13 +547,35 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + get-east-asian-width@1.5.0: resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} engines: {node: '>=18'} @@ -204,6 +593,17 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lint-staged@16.3.1: resolution: {integrity: sha512-bqvvquXzFBAlSbluugR4KXAe4XnO/QZcKVszpkBtqLWa2KEiVy8n6Xp38OeUbv/gOJOX4Vo9u5pFt/ADvbm42Q==} engines: {node: '>=20.17'} @@ -213,10 +613,17 @@ packages: resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} engines: {node: '>=20.0.0'} + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -225,6 +632,19 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} @@ -234,10 +654,53 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -245,6 +708,11 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -257,6 +725,10 @@ packages: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -273,10 +745,29 @@ packages: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tinypool@2.1.0: resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} engines: {node: ^20.0.0 || >=22.0.0} @@ -285,6 +776,43 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -296,6 +824,98 @@ packages: snapshots: + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@oxfmt/binding-android-arm-eabi@0.36.0': optional: true @@ -353,6 +973,89 @@ snapshots: '@oxfmt/binding-win32-x64-msvc@0.36.0': optional: true + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@types/estree@1.0.8': {} + + '@types/node@22.19.13': + dependencies: + undici-types: 6.21.0 + + acorn@8.16.0: {} + ansi-escapes@7.3.0: dependencies: environment: 1.1.0 @@ -361,10 +1064,23 @@ snapshots: ansi-styles@6.2.3: {} + any-promise@1.3.0: {} + braces@3.0.3: dependencies: fill-range: 7.1.1 + bundle-require@5.1.0(esbuild@0.27.3): + dependencies: + esbuild: 0.27.3 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -378,16 +1094,68 @@ snapshots: commander@14.0.3: {} + commander@4.1.1: {} + + confbox@0.1.8: {} + + consola@3.4.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + emoji-regex@10.6.0: {} environment@1.1.0: {} + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + eventemitter3@5.0.4: {} + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.0 + rollup: 4.59.0 + + fsevents@2.3.3: + optional: true + get-east-asian-width@1.5.0: {} husky@9.1.7: {} @@ -398,6 +1166,12 @@ snapshots: is-number@7.0.0: {} + joycon@3.1.1: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + lint-staged@16.3.1: dependencies: commander: 14.0.3 @@ -416,6 +1190,8 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.2 + load-tsconfig@0.2.5: {} + log-update@6.1.0: dependencies: ansi-escapes: 7.3.0 @@ -424,6 +1200,10 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 9.0.2 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -431,6 +1211,23 @@ snapshots: mimic-function@5.0.1: {} + mlly@1.8.0: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + object-assign@4.1.1: {} + onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -459,8 +1256,32 @@ snapshots: '@oxfmt/binding-win32-ia32-msvc': 0.36.0 '@oxfmt/binding-win32-x64-msvc': 0.36.0 + pathe@2.0.3: {} + + picocolors@1.1.1: {} + picomatch@2.3.1: {} + picomatch@4.0.3: {} + + pirates@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + postcss-load-config@6.0.1(yaml@2.8.2): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + yaml: 2.8.2 + + readdirp@4.1.2: {} + + resolve-from@5.0.0: {} + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -468,6 +1289,37 @@ snapshots: rfdc@1.4.1: {} + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + signal-exit@4.1.0: {} slice-ansi@7.1.2: @@ -480,6 +1332,8 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + source-map@0.7.6: {} + string-argv@0.3.2: {} string-width@7.2.0: @@ -497,14 +1351,76 @@ snapshots: dependencies: ansi-regex: 6.2.2 + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinyexec@0.3.2: {} + tinyexec@1.0.2: {} + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinypool@2.1.0: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tree-kill@1.2.2: {} + + ts-interface-checker@0.1.13: {} + + tsup@8.5.1(typescript@5.9.3)(yaml@2.8.2): + dependencies: + bundle-require: 5.1.0(esbuild@0.27.3) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.27.3 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(yaml@2.8.2) + resolve-from: 5.0.0 + rollup: 4.59.0 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + typescript@5.9.3: {} + + ufo@1.6.3: {} + + undici-types@6.21.0: {} + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" From a6c125a6b70dbaedab95751e4e092e5ae9ea0604 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:20:24 +0100 Subject: [PATCH 02/12] chore: add README and fix scripts order in next-basic-auth-proxy Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 46 +++++++++++++++++++++ packages/next-basic-auth-proxy/package.json | 4 +- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 packages/next-basic-auth-proxy/README.md diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md new file mode 100644 index 0000000..026d246 --- /dev/null +++ b/packages/next-basic-auth-proxy/README.md @@ -0,0 +1,46 @@ +# @plainbrew/next-basic-auth-proxy + +Basic Auth handler for Next.js `proxy.ts`. + +## Install + +```sh +pnpm add @plainbrew/next-basic-auth-proxy +``` + +## Usage + +`proxy.ts`: + +```ts +import { basicAuth } from "@plainbrew/next-basic-auth-proxy"; +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +export default async function proxy(request: NextRequest) { + const authResponse = basicAuth(request); + if (authResponse) return authResponse; + + return NextResponse.next(); +} +``` + +## Environment Variables + +| Variable | Description | +| --------------------- | --------------------- | +| `BASIC_AUTH_TARGET` | `all` or `production` | +| `BASIC_AUTH_USER` | Username | +| `BASIC_AUTH_PASSWORD` | Password | + +### `BASIC_AUTH_TARGET` + +| Value | Behavior | +| ------------ | ------------------------------------------- | +| `all` | Apply Basic Auth to all Vercel environments | +| `production` | Apply Basic Auth to Vercel production only | + +### Notes + +- Basic Auth is only applied on Vercel (`VERCEL=1`). Local development is always skipped. +- `BASIC_AUTH_TARGET` is required when running on Vercel. An error is thrown if it is missing or invalid. diff --git a/packages/next-basic-auth-proxy/package.json b/packages/next-basic-auth-proxy/package.json index 074faf3..0e03178 100644 --- a/packages/next-basic-auth-proxy/package.json +++ b/packages/next-basic-auth-proxy/package.json @@ -28,8 +28,8 @@ } }, "scripts": { - "build": "tsup", - "dev": "tsup --watch" + "dev": "tsup --watch", + "build": "tsup" }, "devDependencies": { "@types/node": "^22.0.0", From d38e2544867eb8a9092f988d098d15f2435ddca1 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:22:34 +0100 Subject: [PATCH 03/12] feat: require username/password via options in basicAuth Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 13 +++++++------ packages/next-basic-auth-proxy/src/index.ts | 17 +++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index 026d246..43abc9b 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -18,7 +18,10 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; export default async function proxy(request: NextRequest) { - const authResponse = basicAuth(request); + const authResponse = basicAuth(request, { + username: process.env.BASIC_AUTH_USER ?? "", + password: process.env.BASIC_AUTH_PASSWORD ?? "", + }); if (authResponse) return authResponse; return NextResponse.next(); @@ -27,11 +30,9 @@ export default async function proxy(request: NextRequest) { ## Environment Variables -| Variable | Description | -| --------------------- | --------------------- | -| `BASIC_AUTH_TARGET` | `all` or `production` | -| `BASIC_AUTH_USER` | Username | -| `BASIC_AUTH_PASSWORD` | Password | +| Variable | Description | +| ------------------- | --------------------- | +| `BASIC_AUTH_TARGET` | `all` or `production` | ### `BASIC_AUTH_TARGET` diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 8cad9d8..95ce90f 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -1,6 +1,11 @@ /* eslint-disable n/no-process-env */ -export function basicAuth(request: Request): Response | null { +export type BasicAuthOptions = { + username: string; + password: string; +}; + +export function basicAuth(request: Request, options: BasicAuthOptions): Response | null { function unauthorized() { return new Response("Auth required", { status: 401, @@ -28,15 +33,7 @@ export function basicAuth(request: Request): Response | null { return null; } - const authUser = process.env.BASIC_AUTH_USER; - if (!authUser) { - throw new Error("BASIC_AUTH_USER is not set"); - } - - const authPassword = process.env.BASIC_AUTH_PASSWORD; - if (!authPassword) { - throw new Error("BASIC_AUTH_PASSWORD is not set"); - } + const { username: authUser, password: authPassword } = options; const authorization = request.headers.get("authorization"); if (!authorization) { From f669f343ff611b202cb7ded558a7199bf0af52d9 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:24:19 +0100 Subject: [PATCH 04/12] feat: add dev option to apply Basic Auth in development Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 11 +++++++- packages/next-basic-auth-proxy/src/index.ts | 31 +++++++++++++-------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index 43abc9b..955381c 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -21,6 +21,7 @@ export default async function proxy(request: NextRequest) { const authResponse = basicAuth(request, { username: process.env.BASIC_AUTH_USER ?? "", password: process.env.BASIC_AUTH_PASSWORD ?? "", + // dev: true, // ローカル開発環境でも Basic 認証を適用する場合 }); if (authResponse) return authResponse; @@ -41,7 +42,15 @@ export default async function proxy(request: NextRequest) { | `all` | Apply Basic Auth to all Vercel environments | | `production` | Apply Basic Auth to Vercel production only | +## Options + +| Option | Type | Required | Description | +| ---------- | --------- | -------- | ------------------------------------------------------------ | +| `username` | `string` | ✓ | Basic Auth username | +| `password` | `string` | ✓ | Basic Auth password | +| `dev` | `boolean` | | Apply Basic Auth in `NODE_ENV=development`. Default: `false` | + ### Notes -- Basic Auth is only applied on Vercel (`VERCEL=1`). Local development is always skipped. +- Basic Auth is only applied on Vercel (`VERCEL=1`) by default. Local development is skipped unless `dev: true`. - `BASIC_AUTH_TARGET` is required when running on Vercel. An error is thrown if it is missing or invalid. diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 95ce90f..0ca70c5 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -3,6 +3,8 @@ export type BasicAuthOptions = { username: string; password: string; + /** NODE_ENV=development でも Basic 認証を適用するか。デフォルト: false */ + dev?: boolean; }; export function basicAuth(request: Request, options: BasicAuthOptions): Response | null { @@ -15,22 +17,27 @@ export function basicAuth(request: Request, options: BasicAuthOptions): Response }); } - // Vercel 環境でない場合は認証不要 - if (process.env.VERCEL !== "1") { + const isDev = options.dev === true && process.env.NODE_ENV === "development"; + + // Vercel 環境でなく、dev モードでもない場合は認証不要 + if (process.env.VERCEL !== "1" && !isDev) { return null; } - // BASIC_AUTH_TARGET のバリデーション - if ( - !process.env.BASIC_AUTH_TARGET || - !["all", "production"].includes(process.env.BASIC_AUTH_TARGET) - ) { - throw new Error("BASIC_AUTH_TARGET must be 'all' or 'production'"); - } + // Vercel 環境の場合のみ BASIC_AUTH_TARGET を検証 + if (!isDev) { + // BASIC_AUTH_TARGET のバリデーション + if ( + !process.env.BASIC_AUTH_TARGET || + !["all", "production"].includes(process.env.BASIC_AUTH_TARGET) + ) { + throw new Error("BASIC_AUTH_TARGET must be 'all' or 'production'"); + } - // production ターゲットでも、production 環境以外では認証スキップ - if (process.env.BASIC_AUTH_TARGET === "production" && process.env.VERCEL_ENV !== "production") { - return null; + // production ターゲットでも、production 環境以外では認証スキップ + if (process.env.BASIC_AUTH_TARGET === "production" && process.env.VERCEL_ENV !== "production") { + return null; + } } const { username: authUser, password: authPassword } = options; From 56f6a710f780429056b29743a9b731b31c44befa Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:27:37 +0100 Subject: [PATCH 05/12] feat: replace BASIC_AUTH_TARGET with vercelEnvTarget option Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 31 +++++++++------------ packages/next-basic-auth-proxy/src/index.ts | 26 +++++++++-------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index 955381c..af4a8a7 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -21,6 +21,7 @@ export default async function proxy(request: NextRequest) { const authResponse = basicAuth(request, { username: process.env.BASIC_AUTH_USER ?? "", password: process.env.BASIC_AUTH_PASSWORD ?? "", + // vercelEnvTarget: "all", // すべての Vercel 環境で Basic 認証を適用する場合 // dev: true, // ローカル開発環境でも Basic 認証を適用する場合 }); if (authResponse) return authResponse; @@ -29,28 +30,22 @@ export default async function proxy(request: NextRequest) { } ``` -## Environment Variables - -| Variable | Description | -| ------------------- | --------------------- | -| `BASIC_AUTH_TARGET` | `all` or `production` | - -### `BASIC_AUTH_TARGET` +## Options -| Value | Behavior | -| ------------ | ------------------------------------------- | -| `all` | Apply Basic Auth to all Vercel environments | -| `production` | Apply Basic Auth to Vercel production only | +| Option | Type | Required | Default | Description | +| ----------------- | --------- | -------- | ------------------- | ------------------------------------------ | +| `username` | `string` | ✓ | | Basic Auth username | +| `password` | `string` | ✓ | | Basic Auth password | +| `vercelEnvTarget` | `string` | | `'only-production'` | Vercel environments to apply Basic Auth | +| `dev` | `boolean` | | `false` | Apply Basic Auth in `NODE_ENV=development` | -## Options +### `vercelEnvTarget` -| Option | Type | Required | Description | -| ---------- | --------- | -------- | ------------------------------------------------------------ | -| `username` | `string` | ✓ | Basic Auth username | -| `password` | `string` | ✓ | Basic Auth password | -| `dev` | `boolean` | | Apply Basic Auth in `NODE_ENV=development`. Default: `false` | +| Value | Behavior | +| ----------------- | ------------------------------------------- | +| `only-production` | Apply Basic Auth to Vercel production only | +| `all` | Apply Basic Auth to all Vercel environments | ### Notes - Basic Auth is only applied on Vercel (`VERCEL=1`) by default. Local development is skipped unless `dev: true`. -- `BASIC_AUTH_TARGET` is required when running on Vercel. An error is thrown if it is missing or invalid. diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 0ca70c5..9341272 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -1,9 +1,19 @@ /* eslint-disable n/no-process-env */ +export type VercelEnvTarget = "only-production" | "all"; + export type BasicAuthOptions = { username: string; password: string; - /** NODE_ENV=development でも Basic 認証を適用するか。デフォルト: false */ + /** + * Vercel 環境のどの範囲で Basic 認証を適用するか + * @default 'only-production' + */ + vercelEnvTarget?: VercelEnvTarget; + /** + * NODE_ENV=development でも Basic 認証を適用するか + * @default false + */ dev?: boolean; }; @@ -24,18 +34,12 @@ export function basicAuth(request: Request, options: BasicAuthOptions): Response return null; } - // Vercel 環境の場合のみ BASIC_AUTH_TARGET を検証 + // Vercel 環境の場合のみ vercelEnvTarget を検証 if (!isDev) { - // BASIC_AUTH_TARGET のバリデーション - if ( - !process.env.BASIC_AUTH_TARGET || - !["all", "production"].includes(process.env.BASIC_AUTH_TARGET) - ) { - throw new Error("BASIC_AUTH_TARGET must be 'all' or 'production'"); - } + const vercelEnvTarget = options.vercelEnvTarget ?? "only-production"; - // production ターゲットでも、production 環境以外では認証スキップ - if (process.env.BASIC_AUTH_TARGET === "production" && process.env.VERCEL_ENV !== "production") { + // only-production ターゲットでも、production 環境以外では認証スキップ + if (vercelEnvTarget === "only-production" && process.env.VERCEL_ENV !== "production") { return null; } } From 7cd6bb0ee39a9858e1aef529bccf1ac1149c3c5d Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:29:16 +0100 Subject: [PATCH 06/12] chore: rename authResponse to basicAuthResponse in README example Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index af4a8a7..52476ae 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -18,13 +18,13 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; export default async function proxy(request: NextRequest) { - const authResponse = basicAuth(request, { + const basicAuthResponse = basicAuth(request, { username: process.env.BASIC_AUTH_USER ?? "", password: process.env.BASIC_AUTH_PASSWORD ?? "", // vercelEnvTarget: "all", // すべての Vercel 環境で Basic 認証を適用する場合 // dev: true, // ローカル開発環境でも Basic 認証を適用する場合 }); - if (authResponse) return authResponse; + if (basicAuthResponse) return basicAuthResponse; return NextResponse.next(); } From bf73e5cc2a07bf0eb78ec85bf0cf1347c08b9ede Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:43:43 +0100 Subject: [PATCH 07/12] refactor: destructure options params and separate isDev/isVercel blocks Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/src/index.ts | 27 +++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 9341272..60990cb 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -17,7 +17,15 @@ export type BasicAuthOptions = { dev?: boolean; }; -export function basicAuth(request: Request, options: BasicAuthOptions): Response | null { +export function basicAuth( + request: Request, + { + username: authUser, + password: authPassword, + vercelEnvTarget = "only-production", + dev = false, + }: BasicAuthOptions, +): Response | null { function unauthorized() { return new Response("Auth required", { status: 401, @@ -27,25 +35,18 @@ export function basicAuth(request: Request, options: BasicAuthOptions): Response }); } - const isDev = options.dev === true && process.env.NODE_ENV === "development"; - - // Vercel 環境でなく、dev モードでもない場合は認証不要 - if (process.env.VERCEL !== "1" && !isDev) { - return null; + if (process.env.NODE_ENV === "development") { + if (!dev) { + return null; + } } - // Vercel 環境の場合のみ vercelEnvTarget を検証 - if (!isDev) { - const vercelEnvTarget = options.vercelEnvTarget ?? "only-production"; - - // only-production ターゲットでも、production 環境以外では認証スキップ + if (process.env.VERCEL === "1") { if (vercelEnvTarget === "only-production" && process.env.VERCEL_ENV !== "production") { return null; } } - const { username: authUser, password: authPassword } = options; - const authorization = request.headers.get("authorization"); if (!authorization) { return unauthorized(); From 8074647415a651575428d9da20c99ce1eda1c666 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:47:37 +0100 Subject: [PATCH 08/12] feat: add 'disabled' to VercelEnvTarget to skip auth on all Vercel envs Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 9 +++++---- packages/next-basic-auth-proxy/src/index.ts | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index 52476ae..1eb1558 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -41,10 +41,11 @@ export default async function proxy(request: NextRequest) { ### `vercelEnvTarget` -| Value | Behavior | -| ----------------- | ------------------------------------------- | -| `only-production` | Apply Basic Auth to Vercel production only | -| `all` | Apply Basic Auth to all Vercel environments | +| Value | Behavior | +| ----------------- | --------------------------------------------- | +| `only-production` | Apply Basic Auth to Vercel production only | +| `all` | Apply Basic Auth to all Vercel environments | +| `disabled` | Disable Basic Auth on all Vercel environments | ### Notes diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 60990cb..6f8ac5b 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -1,6 +1,6 @@ /* eslint-disable n/no-process-env */ -export type VercelEnvTarget = "only-production" | "all"; +export type VercelEnvTarget = "only-production" | "all" | "disabled"; export type BasicAuthOptions = { username: string; @@ -42,6 +42,9 @@ export function basicAuth( } if (process.env.VERCEL === "1") { + if (vercelEnvTarget === "disabled") { + return null; + } if (vercelEnvTarget === "only-production" && process.env.VERCEL_ENV !== "production") { return null; } From b7379535e930bf126ea6c09f020699bdb4e3aa42 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:48:50 +0100 Subject: [PATCH 09/12] chore: rename authUser to authUsername and user to username Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/src/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 6f8ac5b..7cfc61f 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -20,7 +20,7 @@ export type BasicAuthOptions = { export function basicAuth( request: Request, { - username: authUser, + username: authUsername, password: authPassword, vercelEnvTarget = "only-production", dev = false, @@ -61,8 +61,8 @@ export function basicAuth( } try { - const [user, password] = atob(authValue).split(":"); - if (user !== authUser || password !== authPassword) { + const [username, password] = atob(authValue).split(":"); + if (username !== authUsername || password !== authPassword) { return unauthorized(); } } catch { From ded65c72451ec11ffd105dca03c916a468b9ef84 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:49:49 +0100 Subject: [PATCH 10/12] chore: remove eslint-disable comment Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/next-basic-auth-proxy/src/index.ts index 7cfc61f..665abf5 100644 --- a/packages/next-basic-auth-proxy/src/index.ts +++ b/packages/next-basic-auth-proxy/src/index.ts @@ -1,5 +1,3 @@ -/* eslint-disable n/no-process-env */ - export type VercelEnvTarget = "only-production" | "all" | "disabled"; export type BasicAuthOptions = { From 91ee0a9d62b2899b592d9374542d3c88223b72be Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 19:56:32 +0100 Subject: [PATCH 11/12] docs: unify README comments to English Co-Authored-By: Claude Sonnet 4.6 --- packages/next-basic-auth-proxy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next-basic-auth-proxy/README.md b/packages/next-basic-auth-proxy/README.md index 1eb1558..62b0fb7 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/next-basic-auth-proxy/README.md @@ -21,8 +21,8 @@ export default async function proxy(request: NextRequest) { const basicAuthResponse = basicAuth(request, { username: process.env.BASIC_AUTH_USER ?? "", password: process.env.BASIC_AUTH_PASSWORD ?? "", - // vercelEnvTarget: "all", // すべての Vercel 環境で Basic 認証を適用する場合 - // dev: true, // ローカル開発環境でも Basic 認証を適用する場合 + // vercelEnvTarget: "all", // Apply Basic Auth to all Vercel environments + // dev: true, // Apply Basic Auth in local development }); if (basicAuthResponse) return basicAuthResponse; From 9e5073a0751f411cfd8c94d474698d3c3efbe23a Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Mon, 2 Mar 2026 20:07:23 +0100 Subject: [PATCH 12/12] refactor: rename next-basic-auth-proxy to vercel-basic-auth Co-Authored-By: Claude Sonnet 4.6 --- .../.gitignore | 0 .../README.md | 8 ++++---- .../package.json | 7 +++---- .../src/index.ts | 0 .../tsconfig.json | 0 .../tsup.config.ts | 0 pnpm-lock.yaml | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/.gitignore (100%) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/README.md (90%) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/package.json (82%) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/src/index.ts (100%) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/tsconfig.json (100%) rename packages/{next-basic-auth-proxy => vercel-basic-auth}/tsup.config.ts (100%) diff --git a/packages/next-basic-auth-proxy/.gitignore b/packages/vercel-basic-auth/.gitignore similarity index 100% rename from packages/next-basic-auth-proxy/.gitignore rename to packages/vercel-basic-auth/.gitignore diff --git a/packages/next-basic-auth-proxy/README.md b/packages/vercel-basic-auth/README.md similarity index 90% rename from packages/next-basic-auth-proxy/README.md rename to packages/vercel-basic-auth/README.md index 62b0fb7..a8a47f8 100644 --- a/packages/next-basic-auth-proxy/README.md +++ b/packages/vercel-basic-auth/README.md @@ -1,11 +1,11 @@ -# @plainbrew/next-basic-auth-proxy +# @plainbrew/vercel-basic-auth -Basic Auth handler for Next.js `proxy.ts`. +Basic Auth handler for Vercel Edge Middleware. ## Install ```sh -pnpm add @plainbrew/next-basic-auth-proxy +pnpm add @plainbrew/vercel-basic-auth ``` ## Usage @@ -13,7 +13,7 @@ pnpm add @plainbrew/next-basic-auth-proxy `proxy.ts`: ```ts -import { basicAuth } from "@plainbrew/next-basic-auth-proxy"; +import { basicAuth } from "@plainbrew/vercel-basic-auth"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; diff --git a/packages/next-basic-auth-proxy/package.json b/packages/vercel-basic-auth/package.json similarity index 82% rename from packages/next-basic-auth-proxy/package.json rename to packages/vercel-basic-auth/package.json index 0e03178..0c3f727 100644 --- a/packages/next-basic-auth-proxy/package.json +++ b/packages/vercel-basic-auth/package.json @@ -1,12 +1,11 @@ { - "name": "@plainbrew/next-basic-auth-proxy", + "name": "@plainbrew/vercel-basic-auth", "version": "0.0.0", - "description": "Basic Auth handler for Next.js proxy.ts", + "description": "Basic Auth handler for Vercel Edge Middleware", "keywords": [ "basic-auth", "middleware", - "next.js", - "proxy" + "vercel" ], "license": "MIT", "files": [ diff --git a/packages/next-basic-auth-proxy/src/index.ts b/packages/vercel-basic-auth/src/index.ts similarity index 100% rename from packages/next-basic-auth-proxy/src/index.ts rename to packages/vercel-basic-auth/src/index.ts diff --git a/packages/next-basic-auth-proxy/tsconfig.json b/packages/vercel-basic-auth/tsconfig.json similarity index 100% rename from packages/next-basic-auth-proxy/tsconfig.json rename to packages/vercel-basic-auth/tsconfig.json diff --git a/packages/next-basic-auth-proxy/tsup.config.ts b/packages/vercel-basic-auth/tsup.config.ts similarity index 100% rename from packages/next-basic-auth-proxy/tsup.config.ts rename to packages/vercel-basic-auth/tsup.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc4c1dc..a800422 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^0.36.0 version: 0.36.0 - packages/next-basic-auth-proxy: + packages/vercel-basic-auth: devDependencies: '@types/node': specifier: ^22.0.0