diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 72% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md index e3d172c..06b2fcb 100644 --- a/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,3 +1,4 @@ + # Contributor Covenant Code of Conduct ## Our Pledge @@ -6,8 +7,8 @@ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. @@ -17,23 +18,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community include: -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the - overall community +* Focusing on what is best not just for us as individuals, but for the overall + community Examples of unacceptable behavior include: -- The use of sexualized language or imagery, and sexual attention or - advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -52,7 +53,7 @@ decisions when appropriate. This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, +Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. @@ -60,7 +61,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -info@bestbytes.de. +info@bestbytes.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the @@ -82,15 +83,15 @@ behavior was inappropriate. A public apology may be requested. ### 2. Warning -**Community Impact**: A violation through a single incident or series -of actions. +**Community Impact**: A violation through a single incident or series of +actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. +like social media. Violating these terms may lead to a temporary or permanent +ban. ### 3. Temporary Ban @@ -109,20 +110,24 @@ Violating these terms may lead to a permanent ban. standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. -**Consequence**: A permanent ban from any sort of public interaction within -the community. +**Consequence**: A permanent ban from any sort of public interaction within the +community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8bc7e55 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,25 @@ +version: 2 + +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + day: 'sunday' + interval: 'weekly' + groups: + github-actions: + patterns: ['*'] + + # https://github.com/dependabot/dependabot-core/issues/6528 + #- package-ecosystem: npm + # directory: '/' + # schedule: + # day: sunday + # interval: weekly + # groups: + # npm-security: + # applies-to: security-updates + # patterns: ['*'] + # npm-update: + # applies-to: version-updates + # patterns: ['*'] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e89ea70 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,36 @@ +name: Test Branch + +on: + push: + branches: [ main ] + pull_request: + merge_group: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + with: + bun-version-file: package.json + + - name: Run install + run: | + bun install + git diff --exit-code + + - name: Run lint + run: bun run lint + + - name: Run type check + run: bun run type-check + + #- name: Run test + # run: bun test diff --git a/LICENSE b/LICENSE index 10db30c..2b3a107 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2025 bestbytes +Copyright (c) foomo by bestbytes Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index daf5896..d4934fd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://github.com/foomo/next-proxy-middleware/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/foomo/next-proxy-middleware/actions/workflows/test.yml) + # @foomo/next-proxy-middleware A Next.js middleware for proxying requests to external services with advanced configuration options. @@ -79,4 +81,6 @@ Contributions are welcome! Please fork the repository and submit a pull request. ## License -MIT License +Distributed under MIT License, please see license file within the code for more details. + +_Made with ♥ [foomo](https://www.foomo.org) by [bestbytes](https://www.bestbytes.com)_ diff --git a/biome.json b/biome.json index 2eb0751..a012eeb 100644 --- a/biome.json +++ b/biome.json @@ -1,30 +1,35 @@ { "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "vcs": { - "enabled": false, - "clientKind": "git", - "useIgnoreFile": false - }, - "files": { - "ignoreUnknown": false, - "ignore": [] - }, - "formatter": { - "enabled": true, - "indentStyle": "tab" - }, "organizeImports": { "enabled": true }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, "linter": { "enabled": true, "rules": { "recommended": true } }, + "formatter": { + "enabled": true, + "lineWidth": 80, + "useEditorconfig": true + }, "javascript": { "formatter": { "quoteStyle": "double" } + }, + "json": { + "parser": { + "allowComments": true + } + }, + "files": { + "ignoreUnknown": true } } diff --git a/bun.lock b/bun.lock index acc2d12..564e144 100644 --- a/bun.lock +++ b/bun.lock @@ -3,16 +3,34 @@ "workspaces": { "": { "name": "@foomo/nextproxy", - "devDependencies": { - "@types/bun": "latest", + "optionalDependencies": { + "@biomejs/biome": "1.9.4", }, "peerDependencies": { "next": "15", - "typescript": "^5.0.0", + "typescript": "5", }, }, }, "packages": { + "@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "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" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="], + "@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], @@ -75,14 +93,6 @@ "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], - "@types/bun": ["@types/bun@1.2.1", "", { "dependencies": { "bun-types": "1.2.1" } }, "sha512-iiCeMAKMkft8EPQJxSbpVRD0DKqrh91w40zunNajce3nMNNFd/LnAquVisSZC+UpTMjDwtcdyzbWct08IvEqRA=="], - - "@types/node": ["@types/node@22.12.0", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA=="], - - "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], - - "bun-types": ["bun-types@1.2.1", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-p7bmXUWmrPWxhcbFVk7oUXM5jAGt94URaoa3qf4mz43MEhNAo/ot1urzBqctgvuq7y9YxkuN51u+/qm4BiIsHw=="], - "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], "caniuse-lite": ["caniuse-lite@1.0.30001697", "", {}, "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ=="], @@ -130,7 +140,5 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], - - "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], } } diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..7f95b4e --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,5 @@ +# https://bun.sh/docs/runtime/bunfig +telemetry = false + +[install] +exact = true diff --git a/package.json b/package.json index 1edd29f..404b4b3 100644 --- a/package.json +++ b/package.json @@ -5,23 +5,29 @@ "type": "module", "scripts": { "build": "tsc", + "lint": "biome check ./", + "lint:fix": "biome check --write ./", + "lint:fix:unsafe": "biome check --write --unsafe ./", + "type-check": "tsc --noEmit", "publish": "bun run build && bun publish --access public" }, "publishConfig": { "tag": "next" }, - "devDependencies": { - "@types/bun": "latest" - }, - "peerDependencies": { - "typescript": "^5.0.0", - "next": "15" - }, "types": "dist/index.d.ts", "exports": { ".": { "import": "./src/index.ts", "require": "./dist/index.js" } - } + }, + "devDependencies": {}, + "optionalDependencies": { + "@biomejs/biome": "1.9.4" + }, + "peerDependencies": { + "next": "15", + "typescript": "5" + }, + "packageManager": "bun@1.2.2" } diff --git a/src/index.ts b/src/index.ts index 02ba6e2..230777b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,3 @@ -import { headers } from "next/headers"; import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; @@ -45,7 +44,7 @@ export type DevProxyConfig = { */ export const createProxyMiddleware = (config: DevProxyConfig) => { if (config.debug) { - console.log("[PROXY]", "starting proxy with config", config); + console.debug("[PROXY]", "starting proxy with config", config); } if (config.remoteUrl === undefined) { @@ -93,7 +92,7 @@ export const createProxyMiddleware = (config: DevProxyConfig) => { }); if (config.debug) { - console.log("[PROXY]", "received response from remote", { + console.debug("[PROXY]", "received response from remote", { // biome-ignore lint/suspicious/noExplicitAny: inconsistency in TS headers: Object.fromEntries(backendResponse.headers as any), }); @@ -105,7 +104,7 @@ export const createProxyMiddleware = (config: DevProxyConfig) => { if (setCookieHeaders) { try { if (config.debug) { - console.log("[PROXY]", "setCookieHeaders", setCookieHeaders); + console.debug("[PROXY]", "setCookieHeaders", setCookieHeaders); } // const origin = new URL(request.headers.get("host") ?? ""); const rewrittenCookies = setCookieHeaders.split(",").map((cookie) => { @@ -114,7 +113,7 @@ export const createProxyMiddleware = (config: DevProxyConfig) => { }); if (config.debug) { - console.log("[PROXY]", "rewrittenCookies", rewrittenCookies); + console.debug("[PROXY]", "rewrittenCookies", rewrittenCookies); } remoteHeaders.set("set-cookie", rewrittenCookies.join(",")); } catch (e) { @@ -123,12 +122,10 @@ export const createProxyMiddleware = (config: DevProxyConfig) => { } } - const response = new NextResponse(backendResponse.body, { + return new NextResponse(backendResponse.body, { ...backendResponse, headers: responseHeaders, status: backendResponse.status, }); - - return response; }; };