adapter-edge 0.1.0
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/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/index.cjs +58 -0
- package/dist/index.d.cts +48 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +31 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vincent Adiasor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# adapter-edge
|
|
2
|
+
|
|
3
|
+
A lightweight adapter for running a single, framework-agnostic request handler
|
|
4
|
+
on any edge runtime that speaks the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) —
|
|
5
|
+
Cloudflare Workers, Vercel Edge, Deno Deploy, Netlify Edge, Bun, and more.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install adapter-edge
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createEdgeAdapter, toFetchHandler } from "adapter-edge";
|
|
17
|
+
|
|
18
|
+
const handler = createEdgeAdapter(
|
|
19
|
+
async (request, ctx) => {
|
|
20
|
+
return Response.json({ url: request.url, hasEnv: !!ctx.env });
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
middleware: [
|
|
24
|
+
(next) => async (req, ctx) => {
|
|
25
|
+
const res = await next(req, ctx);
|
|
26
|
+
res.headers.set("x-powered-by", "adapter-edge");
|
|
27
|
+
return res;
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Cloudflare Workers / Vercel Edge style export:
|
|
34
|
+
export default { fetch: toFetchHandler(handler) };
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
### `createEdgeAdapter(handler, options?)`
|
|
40
|
+
|
|
41
|
+
Composes a handler with middleware and error handling into a single `EdgeHandler`.
|
|
42
|
+
|
|
43
|
+
- `middleware` — array of `EdgeMiddleware`, applied outermost-first.
|
|
44
|
+
- `onError(error, request)` — called when the handler throws; defaults to a JSON 500.
|
|
45
|
+
|
|
46
|
+
### `toFetchHandler(handler)`
|
|
47
|
+
|
|
48
|
+
Adapts an `EdgeHandler` to the `(request, env, ctx)` signature used by
|
|
49
|
+
Cloudflare Workers and Vercel Edge functions.
|
|
50
|
+
|
|
51
|
+
### `notFound`
|
|
52
|
+
|
|
53
|
+
A ready-made `EdgeHandler` that returns `404 Not Found`.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
createEdgeAdapter: () => createEdgeAdapter,
|
|
24
|
+
notFound: () => notFound,
|
|
25
|
+
toFetchHandler: () => toFetchHandler
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var defaultOnError = (error) => {
|
|
29
|
+
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
30
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
31
|
+
status: 500,
|
|
32
|
+
headers: { "content-type": "application/json" }
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
function createEdgeAdapter(handler, options = {}) {
|
|
36
|
+
const { middleware = [], onError = defaultOnError } = options;
|
|
37
|
+
const composed = middleware.reduceRight(
|
|
38
|
+
(next, mw) => mw(next),
|
|
39
|
+
handler
|
|
40
|
+
);
|
|
41
|
+
return async (request, context) => {
|
|
42
|
+
try {
|
|
43
|
+
return await composed(request, context);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
return onError(error, request);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function toFetchHandler(handler) {
|
|
50
|
+
return (request, env, ctx) => handler(request, { env, waitUntil: ctx?.waitUntil });
|
|
51
|
+
}
|
|
52
|
+
var notFound = () => new Response("Not Found", { status: 404 });
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
createEdgeAdapter,
|
|
56
|
+
notFound,
|
|
57
|
+
toFetchHandler
|
|
58
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapter-edge
|
|
3
|
+
*
|
|
4
|
+
* A tiny adapter that lets you write a single, framework-agnostic request
|
|
5
|
+
* handler and run it on any edge runtime that speaks the Fetch API
|
|
6
|
+
* (Cloudflare Workers, Vercel Edge, Deno Deploy, Netlify Edge, Bun, etc.).
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Extra context passed alongside the request. Edge runtimes expose different
|
|
10
|
+
* shapes here (env bindings, waitUntil, etc.), so it is intentionally open.
|
|
11
|
+
*/
|
|
12
|
+
interface EdgeContext {
|
|
13
|
+
/** Runtime-provided environment / bindings (e.g. Cloudflare `env`). */
|
|
14
|
+
env?: Record<string, unknown>;
|
|
15
|
+
/** Schedule background work that outlives the response, when supported. */
|
|
16
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
17
|
+
/** Anything else the host runtime wants to surface. */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A framework-agnostic handler. Receives a standard `Request` plus an
|
|
22
|
+
* `EdgeContext` and returns a `Response` (or a promise of one).
|
|
23
|
+
*/
|
|
24
|
+
type EdgeHandler = (request: Request, context: EdgeContext) => Response | Promise<Response>;
|
|
25
|
+
/** Middleware wraps a handler, optionally short-circuiting it. */
|
|
26
|
+
type EdgeMiddleware = (handler: EdgeHandler) => EdgeHandler;
|
|
27
|
+
interface CreateEdgeAdapterOptions {
|
|
28
|
+
/** Middleware applied outermost-first (left to right). */
|
|
29
|
+
middleware?: EdgeMiddleware[];
|
|
30
|
+
/** Called when the handler throws. Defaults to a 500 response. */
|
|
31
|
+
onError?: (error: unknown, request: Request) => Response | Promise<Response>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compose a handler with middleware and error handling into a single
|
|
35
|
+
* `EdgeHandler` you can mount on any edge runtime.
|
|
36
|
+
*/
|
|
37
|
+
declare function createEdgeAdapter(handler: EdgeHandler, options?: CreateEdgeAdapterOptions): EdgeHandler;
|
|
38
|
+
/**
|
|
39
|
+
* Convenience wrapper for Cloudflare Workers / Vercel Edge style exports,
|
|
40
|
+
* mapping their `(request, env, ctx)` signature onto an `EdgeHandler`.
|
|
41
|
+
*/
|
|
42
|
+
declare function toFetchHandler(handler: EdgeHandler): (request: Request, env?: Record<string, unknown>, ctx?: {
|
|
43
|
+
waitUntil?: (p: Promise<unknown>) => void;
|
|
44
|
+
}) => Response | Promise<Response>;
|
|
45
|
+
/** A no-op handler returning 404 — handy as a fallback. */
|
|
46
|
+
declare const notFound: EdgeHandler;
|
|
47
|
+
|
|
48
|
+
export { type CreateEdgeAdapterOptions, type EdgeContext, type EdgeHandler, type EdgeMiddleware, createEdgeAdapter, notFound, toFetchHandler };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapter-edge
|
|
3
|
+
*
|
|
4
|
+
* A tiny adapter that lets you write a single, framework-agnostic request
|
|
5
|
+
* handler and run it on any edge runtime that speaks the Fetch API
|
|
6
|
+
* (Cloudflare Workers, Vercel Edge, Deno Deploy, Netlify Edge, Bun, etc.).
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Extra context passed alongside the request. Edge runtimes expose different
|
|
10
|
+
* shapes here (env bindings, waitUntil, etc.), so it is intentionally open.
|
|
11
|
+
*/
|
|
12
|
+
interface EdgeContext {
|
|
13
|
+
/** Runtime-provided environment / bindings (e.g. Cloudflare `env`). */
|
|
14
|
+
env?: Record<string, unknown>;
|
|
15
|
+
/** Schedule background work that outlives the response, when supported. */
|
|
16
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
17
|
+
/** Anything else the host runtime wants to surface. */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A framework-agnostic handler. Receives a standard `Request` plus an
|
|
22
|
+
* `EdgeContext` and returns a `Response` (or a promise of one).
|
|
23
|
+
*/
|
|
24
|
+
type EdgeHandler = (request: Request, context: EdgeContext) => Response | Promise<Response>;
|
|
25
|
+
/** Middleware wraps a handler, optionally short-circuiting it. */
|
|
26
|
+
type EdgeMiddleware = (handler: EdgeHandler) => EdgeHandler;
|
|
27
|
+
interface CreateEdgeAdapterOptions {
|
|
28
|
+
/** Middleware applied outermost-first (left to right). */
|
|
29
|
+
middleware?: EdgeMiddleware[];
|
|
30
|
+
/** Called when the handler throws. Defaults to a 500 response. */
|
|
31
|
+
onError?: (error: unknown, request: Request) => Response | Promise<Response>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compose a handler with middleware and error handling into a single
|
|
35
|
+
* `EdgeHandler` you can mount on any edge runtime.
|
|
36
|
+
*/
|
|
37
|
+
declare function createEdgeAdapter(handler: EdgeHandler, options?: CreateEdgeAdapterOptions): EdgeHandler;
|
|
38
|
+
/**
|
|
39
|
+
* Convenience wrapper for Cloudflare Workers / Vercel Edge style exports,
|
|
40
|
+
* mapping their `(request, env, ctx)` signature onto an `EdgeHandler`.
|
|
41
|
+
*/
|
|
42
|
+
declare function toFetchHandler(handler: EdgeHandler): (request: Request, env?: Record<string, unknown>, ctx?: {
|
|
43
|
+
waitUntil?: (p: Promise<unknown>) => void;
|
|
44
|
+
}) => Response | Promise<Response>;
|
|
45
|
+
/** A no-op handler returning 404 — handy as a fallback. */
|
|
46
|
+
declare const notFound: EdgeHandler;
|
|
47
|
+
|
|
48
|
+
export { type CreateEdgeAdapterOptions, type EdgeContext, type EdgeHandler, type EdgeMiddleware, createEdgeAdapter, notFound, toFetchHandler };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var defaultOnError = (error) => {
|
|
3
|
+
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
4
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
5
|
+
status: 500,
|
|
6
|
+
headers: { "content-type": "application/json" }
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
function createEdgeAdapter(handler, options = {}) {
|
|
10
|
+
const { middleware = [], onError = defaultOnError } = options;
|
|
11
|
+
const composed = middleware.reduceRight(
|
|
12
|
+
(next, mw) => mw(next),
|
|
13
|
+
handler
|
|
14
|
+
);
|
|
15
|
+
return async (request, context) => {
|
|
16
|
+
try {
|
|
17
|
+
return await composed(request, context);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return onError(error, request);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function toFetchHandler(handler) {
|
|
24
|
+
return (request, env, ctx) => handler(request, { env, waitUntil: ctx?.waitUntil });
|
|
25
|
+
}
|
|
26
|
+
var notFound = () => new Response("Not Found", { status: 404 });
|
|
27
|
+
export {
|
|
28
|
+
createEdgeAdapter,
|
|
29
|
+
notFound,
|
|
30
|
+
toFetchHandler
|
|
31
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adapter-edge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight adapter for running framework-agnostic handlers on edge runtimes (Cloudflare Workers, Vercel Edge, Deno, etc.).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"edge",
|
|
28
|
+
"adapter",
|
|
29
|
+
"cloudflare-workers",
|
|
30
|
+
"vercel-edge",
|
|
31
|
+
"deno",
|
|
32
|
+
"fetch",
|
|
33
|
+
"handler",
|
|
34
|
+
"serverless"
|
|
35
|
+
],
|
|
36
|
+
"author": "@ydaymad",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"tsup": "^8.0.0",
|
|
43
|
+
"typescript": "^5.4.0",
|
|
44
|
+
"vitest": "^1.5.0"
|
|
45
|
+
}
|
|
46
|
+
}
|