@aryanbansal-launch/edge-utils 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,3 +5,4 @@ export * from "./auth/basic-auth.js";
5
5
  export * from "./security/ip-access.js";
6
6
  export * from "./security/block-bots.js";
7
7
  export * from "./geo/geo-headers.js";
8
+ export * from "./nextjs/rsc.js";
@@ -0,0 +1,16 @@
1
+ export function handleNextJS_RSC(request, options) {
2
+ const RSC_HEADER = 'rsc';
3
+ const RSC_HEADER_VALUE = '1';
4
+ const RSC_QUERY_PARAM = '_rsc';
5
+ const parsedUrl = new URL(request.url);
6
+ const route = parsedUrl.pathname;
7
+ const rscQueryParamExists = !!parsedUrl.searchParams.get(RSC_QUERY_PARAM);
8
+ const rscHeaderExists = request.headers.get(RSC_HEADER) === RSC_HEADER_VALUE;
9
+ const isAffectedPath = options.affectedPaths.includes(route);
10
+ if (isAffectedPath && !rscQueryParamExists && rscHeaderExists) {
11
+ const modifiedRequest = new Request(request);
12
+ modifiedRequest.headers.delete(RSC_HEADER);
13
+ return fetch(modifiedRequest);
14
+ }
15
+ return null;
16
+ }
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@aryanbansal-launch/edge-utils",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
+ "license": "MIT",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "exports": {
7
8
  ".": "./dist/index.js"
8
9
  },
9
- "files": ["dist"],
10
+ "files": [
11
+ "dist"
12
+ ],
10
13
  "scripts": {
11
14
  "build": "tsc"
12
15
  }
package/readme.md CHANGED
@@ -1,29 +1,35 @@
1
- # Edge Utils
1
+ # 🚀 Edge Utils
2
2
 
3
- A collection of high-performance utilities designed for Edge Computing environments (like Cloudflare Workers, Vercel Edge Functions, or Contentstack Launch). These utilities help you handle common tasks like authentication, security, redirection, and geo-location directly at the edge.
3
+ [![npm version](https://img.shields.io/npm/v/@launch/edge-utils.svg)](https://www.npmjs.com/package/@launch/edge-utils)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Platform Support](https://img.shields.io/badge/Platform-Edge-blueviolet.svg)](#platform-support)
4
6
 
5
- ## Table of Contents
7
+ A lightweight, developer-friendly toolkit for **Edge Computing**. Speed up your development on platforms like Cloudflare Workers, Vercel Edge, and Contentstack Launch with production-ready utilities for security, authentication, and routing.
6
8
 
7
- - [Installation](#installation)
8
- - [Usage Example](#usage-example)
9
- - [API Reference](#api-reference)
10
- - [Security](#security)
11
- - [Authentication](#authentication)
12
- - [Redirection](#redirection)
13
- - [Geo Location](#geo-location)
14
- - [Responses](#responses)
9
+ ---
15
10
 
16
- ## Installation
11
+ ## ✨ Features
17
12
 
18
- Install the package via npm:
13
+ - 🛡️ **Security First**: Block AI crawlers and manage IP access with ease.
14
+ - 🔐 **Edge Auth**: Implement Basic Auth directly at the edge for specific hostnames.
15
+ - 📍 **Geo-Aware**: Easily extract location data from request headers.
16
+ - ⚛️ **Next.js Ready**: Built-in fixes for RSC header issues on edge proxies.
17
+ - 🔀 **Smart Routing**: Declarative redirects based on path and method.
18
+ - ⚡ **Zero Dependencies**: Lightweight and optimized for edge runtime limits.
19
+
20
+ ---
21
+
22
+ ## 📦 Installation
19
23
 
20
24
  ```bash
21
25
  npm install @launch/edge-utils
22
26
  ```
23
27
 
24
- ## Usage Example
28
+ ---
29
+
30
+ ## 🛠️ Usage Example
25
31
 
26
- Here is a comprehensive example of how to use multiple utilities in a single edge handler:
32
+ Transform your edge handler into a powerful middleware chain:
27
33
 
28
34
  ```typescript
29
35
  import {
@@ -33,77 +39,134 @@ import {
33
39
  protectWithBasicAuth,
34
40
  ipAccessControl,
35
41
  blockAICrawlers,
36
- getGeoHeaders
42
+ getGeoHeaders,
43
+ handleNextJS_RSC
37
44
  } from "@launch/edge-utils";
38
45
 
39
46
  export default async function handler(request: Request) {
40
- // 1. Block known AI crawlers and bots
47
+ // 1. ⚛️ Fix Next.js RSC issues for specific paths
48
+ const rscResponse = await handleNextJS_RSC(request, {
49
+ affectedPaths: ["/my-rsc-page", "/another-page"]
50
+ });
51
+ if (rscResponse) return rscResponse;
52
+
53
+ // 2. 🛡️ Block AI bots immediately
41
54
  const botResponse = blockAICrawlers(request);
42
55
  if (botResponse) return botResponse;
43
56
 
44
- // 2. IP-based access control
57
+ // 2. 🧱 IP Whitelisting
45
58
  const ipResponse = ipAccessControl(request, { allow: ["203.0.113.10"] });
46
59
  if (ipResponse) return ipResponse;
47
60
 
48
- // 3. Basic Authentication for specific hostnames
61
+ // 3. 🔐 Domain-specific Basic Auth
49
62
  const authResponse = await protectWithBasicAuth(request, {
50
- hostnameIncludes: "test-protected-domain.dev",
63
+ hostnameIncludes: "staging.myapp.com",
51
64
  username: "admin",
52
- password: "securepassword"
65
+ password: "securepassword123"
53
66
  });
54
67
  if (authResponse && authResponse.status === 401) return authResponse;
55
68
 
56
- // 4. Conditional Redirection
69
+ // 4. 🔀 SEO-friendly Redirects
57
70
  const redirectResponse = redirectIfMatch(request, {
58
- path: "/old-page",
59
- method: "GET",
60
- to: "/new-page"
71
+ path: "/legacy-url",
72
+ to: "/modern-url",
73
+ status: 301
61
74
  });
62
75
  if (redirectResponse) return redirectResponse;
63
76
 
64
- // 5. Handle specific routes
65
- if (new URL(request.url).pathname === "/api/status") {
66
- return jsonResponse({ status: "ok", timestamp: new Date() });
77
+ // 5. 📍 Geo-Location Access
78
+ const geo = getGeoHeaders(request);
79
+ if (geo.country === "US") {
80
+ console.log(`User from ${geo.city}, ${geo.region}`);
67
81
  }
68
82
 
69
- // 6. Access Geo-location headers
70
- const geo = getGeoHeaders(request);
71
- console.log("Request from country:", geo.country);
83
+ // 6. 📤 Custom JSON Responses
84
+ if (new URL(request.url).pathname === "/api/health") {
85
+ return jsonResponse({ status: "healthy", region: geo.region });
86
+ }
72
87
 
73
- // 7. Pass through the request if no utility intercepted it
88
+ // 7. 🚀 Pass through to origin
74
89
  return passThrough(request);
75
90
  }
76
91
  ```
77
92
 
78
- ## API Reference
93
+ ---
94
+
95
+ ## 📖 API Reference
96
+
97
+ ### 🛡️ Security
98
+
99
+ #### `blockAICrawlers`
100
+ Blocks common AI crawlers (GPTBot, ClaudeBot, etc.) to protect your content from scraping.
101
+ - **Parameters**: `request: Request`, `bots?: string[]` (optional list to override defaults)
102
+ - **Returns**: `Response` (403) or `null`.
103
+
104
+ #### `ipAccessControl`
105
+ Simple firewall for your edge function.
106
+ - **Options**:
107
+ - `allow`: Array of IPs allowed to access.
108
+ - `deny`: Array of IPs to block.
109
+ - **Returns**: `Response` (403) or `null`.
110
+
111
+ ### 🔐 Authentication
112
+
113
+ #### `protectWithBasicAuth`
114
+ Prompt for credentials based on the hostname.
115
+ - **Options**:
116
+ - `hostnameIncludes`: Match substring in hostname (e.g., ".dev").
117
+ - `username`: Required username.
118
+ - `password`: Required password.
119
+ - `realm`: Optional realm name for the auth prompt.
120
+ - **Returns**: `Promise<Response>` or `null`.
121
+
122
+ ### 🔀 Redirection
123
+
124
+ #### `redirectIfMatch`
125
+ Perform redirects directly at the edge to reduce latency.
126
+ - **Options**:
127
+ - `path`: The path to match.
128
+ - `method`: HTTP method to match (optional, defaults to any).
129
+ - `to`: Target path or URL.
130
+ - `status`: HTTP status code (default: 301).
131
+ - **Returns**: `Response` (Redirect) or `null`.
132
+
133
+ ### 📍 Geo Location
134
+
135
+ #### `getGeoHeaders`
136
+ Extracts geo-information provided by edge platform headers.
137
+ - **Returns**: Object with `country`, `region`, `city`, `latitude`, `longitude`.
79
138
 
80
- ### Security
139
+ ### ⚛️ Next.js
81
140
 
82
- #### `blockAICrawlers(request: Request, bots?: string[]): Response | null`
83
- Blocks common AI crawlers (like GPTBot, ClaudeBot) based on the `User-Agent` header. Returns a `403 Forbidden` response if a bot is detected, otherwise returns `null`.
141
+ #### `handleNextJS_RSC`
142
+ Handles Next.js React Server Component (RSC) header issues on Contentstack Launch. It detects requests to "affected paths" that have the `rsc` header but lack the `_rsc` query parameter, and strips the header to prevent proxy/caching issues.
143
+ - **Options**:
144
+ - `affectedPaths`: Array of pathnames (e.g., `['/shop', '/about']`) where this fix should apply.
145
+ - **Returns**: `Promise<Response>` (the re-fetched request without RSC header) or `null`.
84
146
 
85
- #### `ipAccessControl(request: Request, options: { allow?: string[], deny?: string[] }): Response | null`
86
- Restricts access based on the client's IP address. You can provide an `allow` list or a `deny` list.
147
+ ---
87
148
 
88
- ### Authentication
149
+ ## 🌐 Platform Support
89
150
 
90
- #### `protectWithBasicAuth(request: Request, options: AuthOptions): Promise<Response> | null`
91
- Implements HTTP Basic Authentication. If the hostname matches `hostnameIncludes` and credentials are missing or invalid, it returns a `401 Unauthorized` response with the appropriate headers.
151
+ Optimized for:
152
+ - [Contentstack Launch](https://www.contentstack.com/docs/developers/launch)
153
+ - [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions)
154
+ - [Cloudflare Workers](https://workers.cloudflare.com/)
92
155
 
93
- ### Redirection
156
+ ---
94
157
 
95
- #### `redirectIfMatch(request: Request, options: RedirectOptions): Response | null`
96
- Redirects the request if the URL path and HTTP method match the provided options.
158
+ ## 🤝 Contributing
97
159
 
98
- ### Geo Location
160
+ Contributions are welcome! Please feel free to submit a Pull Request.
99
161
 
100
- #### `getGeoHeaders(request: Request): Record<string, string | null>`
101
- Extracts geo-location information (country, city, region, etc.) from the request headers typically provided by edge platforms.
162
+ 1. Fork the Project
163
+ 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
164
+ 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
165
+ 4. Push to the Branch (`git push origin feature/AmazingFeature`)
166
+ 5. Open a Pull Request
102
167
 
103
- ### Responses
168
+ ---
104
169
 
105
- #### `jsonResponse(data: any, init?: ResponseInit): Response`
106
- A helper to return a JSON response with the correct `Content-Type` header.
170
+ ## 📄 License
107
171
 
108
- #### `passThrough(request: Request): Response`
109
- Continues the request processing by calling `fetch(request)`. Useful at the end of an edge function.
172
+ Distributed under the MIT License. See `LICENSE` for more information.