@aryanbansal-launch/edge-utils 0.1.4 β 0.1.5
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/bin/launch-init.js +6 -10
- package/package.json +1 -1
- package/readme.md +28 -95
package/bin/launch-init.js
CHANGED
|
@@ -83,15 +83,15 @@ async function init() {
|
|
|
83
83
|
console.log(`\n${colors.bright}${colors.cyan}π Edge Utilities: Contentstack Launch Setup${colors.reset}\n`);
|
|
84
84
|
|
|
85
85
|
let actionsTaken = 0;
|
|
86
|
-
let isRoot = true;
|
|
87
86
|
|
|
88
87
|
// 1. Root level check: Look for package.json
|
|
89
88
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
90
89
|
if (!fs.existsSync(packageJsonPath)) {
|
|
91
|
-
|
|
92
|
-
console.log(`${colors.yellow}
|
|
93
|
-
console.log(`${colors.yellow}
|
|
94
|
-
console.log(
|
|
90
|
+
console.log(`${colors.red}β Error: Root directory not detected.${colors.reset}`);
|
|
91
|
+
console.log(`${colors.yellow}Contentstack Launch requires the 'functions' folder to be at your project root${colors.reset}`);
|
|
92
|
+
console.log(`${colors.yellow}(the same directory as your package.json).${colors.reset}\n`);
|
|
93
|
+
console.log(`Please ${colors.bright}cd${colors.reset} into your project root and try again.`);
|
|
94
|
+
process.exit(1);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
try {
|
|
@@ -114,11 +114,7 @@ async function init() {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
// Final Summary Messages based on the state
|
|
117
|
-
if (
|
|
118
|
-
console.log(`\n${colors.yellow}β οΈ Setup detected in a subdirectory!${colors.reset}`);
|
|
119
|
-
console.log(`The 'functions' folder exists here, but Contentstack Launch`);
|
|
120
|
-
console.log(`requires it to be at the ${colors.bright}project root${colors.reset} (next to package.json).`);
|
|
121
|
-
} else if (actionsTaken === 0) {
|
|
117
|
+
if (actionsTaken === 0) {
|
|
122
118
|
console.log(`\n${colors.bright}${colors.blue}π Everything is already set up!${colors.reset}`);
|
|
123
119
|
console.log(`No changes were made to your existing files.`);
|
|
124
120
|
} else {
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
# π Edge Utils
|
|
1
|
+
# π Edge Utils for Contentstack Launch
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@launch/edge-utils)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](#platform-support)
|
|
6
5
|
|
|
7
|
-
A lightweight,
|
|
6
|
+
A lightweight, high-performance toolkit specifically designed for **Contentstack Launch Edge Functions**. Speed up your development with production-ready utilities for security, authentication, routing, and Next.js compatibilityβall optimized to run at the edge.
|
|
8
7
|
|
|
9
8
|
---
|
|
10
9
|
|
|
@@ -13,39 +12,35 @@ A lightweight, developer-friendly toolkit for **Edge Computing**. Speed up your
|
|
|
13
12
|
- π‘οΈ **Security First**: Block AI crawlers and manage IP access with ease.
|
|
14
13
|
- π **Edge Auth**: Implement Basic Auth directly at the edge for specific hostnames.
|
|
15
14
|
- π **Geo-Aware**: Easily extract location data from request headers.
|
|
16
|
-
- βοΈ **Next.js Ready**: Built-in fixes for RSC header issues on
|
|
15
|
+
- βοΈ **Next.js Ready**: Built-in fixes for RSC header issues on Launch proxies.
|
|
17
16
|
- π **Smart Routing**: Declarative redirects based on path and method.
|
|
18
17
|
- β‘ **Zero Dependencies**: Lightweight and optimized for edge runtime limits.
|
|
19
18
|
|
|
20
19
|
---
|
|
21
20
|
|
|
22
|
-
##
|
|
21
|
+
## β‘ Quick Start (Recommended)
|
|
23
22
|
|
|
23
|
+
Set up your entire edge environment in seconds with our automated CLI tool.
|
|
24
|
+
|
|
25
|
+
### 1. Install
|
|
24
26
|
```bash
|
|
25
|
-
npm install @launch/edge-utils
|
|
27
|
+
npm install @aryanbansal-launch/edge-utils
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## β‘ Quick Start (Automatic Setup)
|
|
31
|
-
|
|
32
|
-
If you are using **Contentstack Launch**, you can automatically set up your edge function directory and boilerplate handler with a single command:
|
|
33
|
-
|
|
30
|
+
### 2. Initialize
|
|
31
|
+
Run this command from your **project root**:
|
|
34
32
|
```bash
|
|
35
33
|
npx launch-init
|
|
36
34
|
```
|
|
37
|
-
|
|
38
|
-
This command will:
|
|
39
|
-
1. Create a `functions/` directory in your project root.
|
|
40
|
-
2. Generate a `[proxy].edge.js` file with a production-ready boilerplate.
|
|
35
|
+
This will automatically create the `functions/` directory and a boilerplate `[proxy].edge.js` handler for you.
|
|
41
36
|
|
|
42
37
|
---
|
|
43
38
|
|
|
44
39
|
## π οΈ Usage Example
|
|
45
40
|
|
|
46
|
-
|
|
41
|
+
Once initialized, your `functions/[proxy].edge.js` will look like a powerful middleware chain:
|
|
47
42
|
|
|
48
|
-
```
|
|
43
|
+
```javascript
|
|
49
44
|
import {
|
|
50
45
|
jsonResponse,
|
|
51
46
|
passThrough,
|
|
@@ -55,12 +50,12 @@ import {
|
|
|
55
50
|
blockAICrawlers,
|
|
56
51
|
getGeoHeaders,
|
|
57
52
|
handleNextJS_RSC
|
|
58
|
-
} from "@launch/edge-utils";
|
|
53
|
+
} from "@aryanbansal-launch/edge-utils";
|
|
59
54
|
|
|
60
|
-
export default async function handler(request
|
|
55
|
+
export default async function handler(request, context) {
|
|
61
56
|
// 1. βοΈ Fix Next.js RSC issues for specific paths
|
|
62
57
|
const rscResponse = await handleNextJS_RSC(request, {
|
|
63
|
-
affectedPaths: ["/
|
|
58
|
+
affectedPaths: ["/shop", "/about"]
|
|
64
59
|
});
|
|
65
60
|
if (rscResponse) return rscResponse;
|
|
66
61
|
|
|
@@ -68,11 +63,11 @@ export default async function handler(request: Request) {
|
|
|
68
63
|
const botResponse = blockAICrawlers(request);
|
|
69
64
|
if (botResponse) return botResponse;
|
|
70
65
|
|
|
71
|
-
//
|
|
66
|
+
// 3. π§± IP Whitelisting
|
|
72
67
|
const ipResponse = ipAccessControl(request, { allow: ["203.0.113.10"] });
|
|
73
68
|
if (ipResponse) return ipResponse;
|
|
74
69
|
|
|
75
|
-
//
|
|
70
|
+
// 4. π Domain-specific Basic Auth (e.g., for staging)
|
|
76
71
|
const authResponse = await protectWithBasicAuth(request, {
|
|
77
72
|
hostnameIncludes: "staging.myapp.com",
|
|
78
73
|
username: "admin",
|
|
@@ -80,7 +75,7 @@ export default async function handler(request: Request) {
|
|
|
80
75
|
});
|
|
81
76
|
if (authResponse && authResponse.status === 401) return authResponse;
|
|
82
77
|
|
|
83
|
-
//
|
|
78
|
+
// 5. π SEO-friendly Redirects
|
|
84
79
|
const redirectResponse = redirectIfMatch(request, {
|
|
85
80
|
path: "/legacy-url",
|
|
86
81
|
to: "/modern-url",
|
|
@@ -88,16 +83,9 @@ export default async function handler(request: Request) {
|
|
|
88
83
|
});
|
|
89
84
|
if (redirectResponse) return redirectResponse;
|
|
90
85
|
|
|
91
|
-
//
|
|
86
|
+
// 6. π Geo-Location Access
|
|
92
87
|
const geo = getGeoHeaders(request);
|
|
93
|
-
|
|
94
|
-
console.log(`User from ${geo.city}, ${geo.region}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 6. π€ Custom JSON Responses
|
|
98
|
-
if (new URL(request.url).pathname === "/api/health") {
|
|
99
|
-
return jsonResponse({ status: "healthy", region: geo.region });
|
|
100
|
-
}
|
|
88
|
+
console.log(`Request from ${geo.city}, ${geo.country}`);
|
|
101
89
|
|
|
102
90
|
// 7. π Pass through to origin
|
|
103
91
|
return passThrough(request);
|
|
@@ -109,78 +97,23 @@ export default async function handler(request: Request) {
|
|
|
109
97
|
## π API Reference
|
|
110
98
|
|
|
111
99
|
### π‘οΈ Security
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Blocks common AI crawlers (GPTBot, ClaudeBot, etc.) to protect your content from scraping.
|
|
115
|
-
- **Parameters**: `request: Request`, `bots?: string[]` (optional list to override defaults)
|
|
116
|
-
- **Returns**: `Response` (403) or `null`.
|
|
117
|
-
|
|
118
|
-
#### `ipAccessControl`
|
|
119
|
-
Simple firewall for your edge function.
|
|
120
|
-
- **Options**:
|
|
121
|
-
- `allow`: Array of IPs allowed to access.
|
|
122
|
-
- `deny`: Array of IPs to block.
|
|
123
|
-
- **Returns**: `Response` (403) or `null`.
|
|
100
|
+
- **`blockAICrawlers(request, bots?)`**: Blocks common AI crawlers.
|
|
101
|
+
- **`ipAccessControl(request, { allow?, deny? })`**: Simple IP-based firewall.
|
|
124
102
|
|
|
125
103
|
### π Authentication
|
|
126
|
-
|
|
127
|
-
#### `protectWithBasicAuth`
|
|
128
|
-
Prompt for credentials based on the hostname.
|
|
129
|
-
- **Options**:
|
|
130
|
-
- `hostnameIncludes`: Match substring in hostname (e.g., ".dev").
|
|
131
|
-
- `username`: Required username.
|
|
132
|
-
- `password`: Required password.
|
|
133
|
-
- `realm`: Optional realm name for the auth prompt.
|
|
134
|
-
- **Returns**: `Promise<Response>` or `null`.
|
|
104
|
+
- **`protectWithBasicAuth(request, options)`**: Prompt for credentials based on hostname.
|
|
135
105
|
|
|
136
106
|
### π Redirection
|
|
137
|
-
|
|
138
|
-
#### `redirectIfMatch`
|
|
139
|
-
Perform redirects directly at the edge to reduce latency.
|
|
140
|
-
- **Options**:
|
|
141
|
-
- `path`: The path to match.
|
|
142
|
-
- `method`: HTTP method to match (optional, defaults to any).
|
|
143
|
-
- `to`: Target path or URL.
|
|
144
|
-
- `status`: HTTP status code (default: 301).
|
|
145
|
-
- **Returns**: `Response` (Redirect) or `null`.
|
|
107
|
+
- **`redirectIfMatch(request, options)`**: Perform SEO-friendly redirects at the edge.
|
|
146
108
|
|
|
147
109
|
### π Geo Location
|
|
148
|
-
|
|
149
|
-
#### `getGeoHeaders`
|
|
150
|
-
Extracts geo-information provided by edge platform headers.
|
|
151
|
-
- **Returns**: Object with `country`, `region`, `city`, `latitude`, `longitude`.
|
|
110
|
+
- **`getGeoHeaders(request)`**: Returns an object with `country`, `region`, `city`, `latitude`, `longitude`.
|
|
152
111
|
|
|
153
112
|
### βοΈ Next.js
|
|
154
|
-
|
|
155
|
-
#### `handleNextJS_RSC`
|
|
156
|
-
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.
|
|
157
|
-
- **Options**:
|
|
158
|
-
- `affectedPaths`: Array of pathnames (e.g., `['/shop', '/about']`) where this fix should apply.
|
|
159
|
-
- **Returns**: `Promise<Response>` (the re-fetched request without RSC header) or `null`.
|
|
113
|
+
- **`handleNextJS_RSC(request, { affectedPaths })`**: Resolves RSC header issues on Contentstack Launch.
|
|
160
114
|
|
|
161
115
|
---
|
|
162
116
|
|
|
163
117
|
## π Platform Support
|
|
164
118
|
|
|
165
|
-
|
|
166
|
-
- [Contentstack Launch](https://www.contentstack.com/docs/developers/launch)
|
|
167
|
-
- [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions)
|
|
168
|
-
- [Cloudflare Workers](https://workers.cloudflare.com/)
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## π€ Contributing
|
|
173
|
-
|
|
174
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
175
|
-
|
|
176
|
-
1. Fork the Project
|
|
177
|
-
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
|
178
|
-
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
|
179
|
-
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
|
180
|
-
5. Open a Pull Request
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## π License
|
|
185
|
-
|
|
186
|
-
Distributed under the MIT License. See `LICENSE` for more information.
|
|
119
|
+
This library is exclusively optimized for **[Contentstack Launch](https://www.contentstack.com/docs/developers/launch)**.
|