@lytjs/runtime-edge 6.5.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/README.md +104 -0
- package/dist/index.cjs +179 -0
- package/dist/index.d.cts +89 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.mjs +149 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# @lytjs/runtime-edge
|
|
2
|
+
|
|
3
|
+
LytJS 边缘运行时支持,为边缘计算环境提供完整的支持。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @lytjs/runtime-edge
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 快速开始
|
|
12
|
+
|
|
13
|
+
### 边缘路由器
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createEdgeRouter } from '@lytjs/runtime-edge';
|
|
17
|
+
|
|
18
|
+
const router = createEdgeRouter({
|
|
19
|
+
basePath: '/api',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
router.get('/users', (req, ctx) => {
|
|
23
|
+
return new Response(JSON.stringify({ users: [] }), {
|
|
24
|
+
status: 200,
|
|
25
|
+
headers: { 'Content-Type': 'application/json' },
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
async fetch(request, env, ctx) {
|
|
31
|
+
return router.handle(request, ctx);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 边缘缓存
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { createEdgeCache } from '@lytjs/runtime-edge';
|
|
40
|
+
|
|
41
|
+
const cache = createEdgeCache();
|
|
42
|
+
|
|
43
|
+
// 设置缓存
|
|
44
|
+
await cache.set('key', { data: 'value' }, { ttl: 60000 });
|
|
45
|
+
|
|
46
|
+
// 获取缓存
|
|
47
|
+
const value = await cache.get('key');
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 响应辅助工具
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { jsonResponse, textResponse, htmlResponse, redirectResponse } from '@lytjs/runtime-edge';
|
|
54
|
+
|
|
55
|
+
// JSON 响应
|
|
56
|
+
return jsonResponse({ success: true }, 200);
|
|
57
|
+
|
|
58
|
+
// 文本响应
|
|
59
|
+
return textResponse('Hello World', 200);
|
|
60
|
+
|
|
61
|
+
// HTML 响应
|
|
62
|
+
return htmlResponse('<html><body>Hello</body></html>', 200);
|
|
63
|
+
|
|
64
|
+
// 重定向响应
|
|
65
|
+
return redirectResponse('https://example.com', 302);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 特性
|
|
69
|
+
|
|
70
|
+
- 边缘函数支持
|
|
71
|
+
- 边缘路由器
|
|
72
|
+
- 内存缓存
|
|
73
|
+
- 响应辅助工具
|
|
74
|
+
- 零外部依赖
|
|
75
|
+
|
|
76
|
+
## API
|
|
77
|
+
|
|
78
|
+
### createEdgeRouter(options)
|
|
79
|
+
|
|
80
|
+
创建边缘路由器实例。
|
|
81
|
+
|
|
82
|
+
### createEdgeCache()
|
|
83
|
+
|
|
84
|
+
创建边缘缓存实例。
|
|
85
|
+
|
|
86
|
+
### jsonResponse(data, status)
|
|
87
|
+
|
|
88
|
+
创建 JSON 响应。
|
|
89
|
+
|
|
90
|
+
### textResponse(text, status)
|
|
91
|
+
|
|
92
|
+
创建文本响应。
|
|
93
|
+
|
|
94
|
+
### htmlResponse(html, status)
|
|
95
|
+
|
|
96
|
+
创建 HTML 响应。
|
|
97
|
+
|
|
98
|
+
### redirectResponse(url, status)
|
|
99
|
+
|
|
100
|
+
创建重定向响应。
|
|
101
|
+
|
|
102
|
+
## 许可证
|
|
103
|
+
|
|
104
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
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
|
+
createEdgeCache: () => createEdgeCache,
|
|
24
|
+
createEdgeRouter: () => createEdgeRouter,
|
|
25
|
+
htmlResponse: () => htmlResponse,
|
|
26
|
+
jsonResponse: () => jsonResponse,
|
|
27
|
+
redirectResponse: () => redirectResponse,
|
|
28
|
+
textResponse: () => textResponse
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
function createEdgeCache() {
|
|
32
|
+
const cache = /* @__PURE__ */ new Map();
|
|
33
|
+
return {
|
|
34
|
+
async get(key) {
|
|
35
|
+
const entry = cache.get(key);
|
|
36
|
+
if (!entry) return null;
|
|
37
|
+
if (entry.expires && Date.now() > entry.expires) {
|
|
38
|
+
cache.delete(key);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return entry.value;
|
|
42
|
+
},
|
|
43
|
+
async set(key, value, options = {}) {
|
|
44
|
+
const ttl = options.ttl ?? 6e4;
|
|
45
|
+
const entry = {
|
|
46
|
+
value,
|
|
47
|
+
expires: Date.now() + ttl
|
|
48
|
+
};
|
|
49
|
+
cache.set(key, entry);
|
|
50
|
+
},
|
|
51
|
+
async delete(key) {
|
|
52
|
+
cache.delete(key);
|
|
53
|
+
},
|
|
54
|
+
async clear() {
|
|
55
|
+
cache.clear();
|
|
56
|
+
},
|
|
57
|
+
async has(key) {
|
|
58
|
+
const entry = cache.get(key);
|
|
59
|
+
if (!entry) return false;
|
|
60
|
+
if (entry.expires && Date.now() > entry.expires) {
|
|
61
|
+
cache.delete(key);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function createEdgeRouter(options = {}) {
|
|
69
|
+
const routes = [];
|
|
70
|
+
const basePath = options.basePath ?? "";
|
|
71
|
+
function addRoute(method, path, handler) {
|
|
72
|
+
const fullPath = basePath + path;
|
|
73
|
+
routes.push({ path: fullPath, handler, method });
|
|
74
|
+
}
|
|
75
|
+
function match(request) {
|
|
76
|
+
const url = new URL(request.url);
|
|
77
|
+
const path = url.pathname;
|
|
78
|
+
const method = request.method.toUpperCase();
|
|
79
|
+
for (const route of routes) {
|
|
80
|
+
if (route.method === method && route.path === path) {
|
|
81
|
+
return route;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
async function handle(request, context) {
|
|
87
|
+
const route = match(request);
|
|
88
|
+
if (!route) {
|
|
89
|
+
return {
|
|
90
|
+
status: 404,
|
|
91
|
+
statusText: "Not Found",
|
|
92
|
+
headers: { "Content-Type": "text/plain" }
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const response = await route.handler(
|
|
97
|
+
request,
|
|
98
|
+
context ?? {
|
|
99
|
+
waitUntil: () => {
|
|
100
|
+
},
|
|
101
|
+
passThroughOnException: () => {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
return response;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("Edge handler error:", error);
|
|
108
|
+
return {
|
|
109
|
+
status: 500,
|
|
110
|
+
statusText: "Internal Server Error",
|
|
111
|
+
headers: { "Content-Type": "text/plain" }
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
get: (path, handler) => addRoute("GET", path, handler),
|
|
117
|
+
post: (path, handler) => addRoute("POST", path, handler),
|
|
118
|
+
put: (path, handler) => addRoute("PUT", path, handler),
|
|
119
|
+
delete: (path, handler) => addRoute("DELETE", path, handler),
|
|
120
|
+
patch: (path, handler) => addRoute("PATCH", path, handler),
|
|
121
|
+
match,
|
|
122
|
+
handle
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function jsonResponse(data, status = 200) {
|
|
126
|
+
return {
|
|
127
|
+
status,
|
|
128
|
+
statusText: "OK",
|
|
129
|
+
headers: { "Content-Type": "application/json" },
|
|
130
|
+
body: new ReadableStream({
|
|
131
|
+
start(controller) {
|
|
132
|
+
controller.enqueue(new TextEncoder().encode(JSON.stringify(data)));
|
|
133
|
+
controller.close();
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function textResponse(text, status = 200) {
|
|
139
|
+
return {
|
|
140
|
+
status,
|
|
141
|
+
statusText: "OK",
|
|
142
|
+
headers: { "Content-Type": "text/plain" },
|
|
143
|
+
body: new ReadableStream({
|
|
144
|
+
start(controller) {
|
|
145
|
+
controller.enqueue(new TextEncoder().encode(text));
|
|
146
|
+
controller.close();
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function htmlResponse(html, status = 200) {
|
|
152
|
+
return {
|
|
153
|
+
status,
|
|
154
|
+
statusText: "OK",
|
|
155
|
+
headers: { "Content-Type": "text/html" },
|
|
156
|
+
body: new ReadableStream({
|
|
157
|
+
start(controller) {
|
|
158
|
+
controller.enqueue(new TextEncoder().encode(html));
|
|
159
|
+
controller.close();
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function redirectResponse(location, status = 302) {
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
statusText: "Found",
|
|
168
|
+
headers: { Location: location }
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
172
|
+
0 && (module.exports = {
|
|
173
|
+
createEdgeCache,
|
|
174
|
+
createEdgeRouter,
|
|
175
|
+
htmlResponse,
|
|
176
|
+
jsonResponse,
|
|
177
|
+
redirectResponse,
|
|
178
|
+
textResponse
|
|
179
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/runtime-edge - Type definitions
|
|
3
|
+
*/
|
|
4
|
+
interface EdgeRequest {
|
|
5
|
+
url: string;
|
|
6
|
+
method: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
body?: ReadableStream;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
interface EdgeResponse {
|
|
12
|
+
status: number;
|
|
13
|
+
statusText: string;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body?: ReadableStream;
|
|
16
|
+
}
|
|
17
|
+
interface EdgeContext {
|
|
18
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
19
|
+
passThroughOnException(): void;
|
|
20
|
+
}
|
|
21
|
+
interface EdgeHandler {
|
|
22
|
+
(request: EdgeRequest, context: EdgeContext): Promise<EdgeResponse> | EdgeResponse;
|
|
23
|
+
}
|
|
24
|
+
interface EdgeRouterOptions {
|
|
25
|
+
basePath?: string;
|
|
26
|
+
}
|
|
27
|
+
interface EdgeRoute {
|
|
28
|
+
path: string;
|
|
29
|
+
handler: EdgeHandler;
|
|
30
|
+
method: string;
|
|
31
|
+
}
|
|
32
|
+
interface EdgeRouter {
|
|
33
|
+
get(path: string, handler: EdgeHandler): void;
|
|
34
|
+
post(path: string, handler: EdgeHandler): void;
|
|
35
|
+
put(path: string, handler: EdgeHandler): void;
|
|
36
|
+
delete(path: string, handler: EdgeHandler): void;
|
|
37
|
+
patch(path: string, handler: EdgeHandler): void;
|
|
38
|
+
match(request: EdgeRequest): EdgeRoute | null;
|
|
39
|
+
handle(request: EdgeRequest, context?: EdgeContext): Promise<EdgeResponse>;
|
|
40
|
+
}
|
|
41
|
+
interface EdgeCacheOptions {
|
|
42
|
+
ttl?: number;
|
|
43
|
+
swr?: boolean;
|
|
44
|
+
staleWhileRevalidate?: number;
|
|
45
|
+
}
|
|
46
|
+
interface EdgeCacheEntry<T = unknown> {
|
|
47
|
+
value: T;
|
|
48
|
+
expires: number;
|
|
49
|
+
}
|
|
50
|
+
interface EdgeCache {
|
|
51
|
+
get<T>(key: string): Promise<T | null>;
|
|
52
|
+
set<T>(key: string, value: T, options?: EdgeCacheOptions): Promise<void>;
|
|
53
|
+
delete(key: string): Promise<void>;
|
|
54
|
+
clear(): Promise<void>;
|
|
55
|
+
has(key: string): Promise<boolean>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @lytjs/runtime-edge - LytJS edge runtime support
|
|
60
|
+
*
|
|
61
|
+
* Provides utilities for running LytJS in edge computing environments
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 创建内存边缘缓存
|
|
66
|
+
*/
|
|
67
|
+
declare function createEdgeCache(): EdgeCache;
|
|
68
|
+
/**
|
|
69
|
+
* 创建边缘路由器
|
|
70
|
+
*/
|
|
71
|
+
declare function createEdgeRouter(options?: EdgeRouterOptions): EdgeRouter;
|
|
72
|
+
/**
|
|
73
|
+
* 创建 JSON 响应
|
|
74
|
+
*/
|
|
75
|
+
declare function jsonResponse(data: unknown, status?: number): EdgeResponse;
|
|
76
|
+
/**
|
|
77
|
+
* 创建文本响应
|
|
78
|
+
*/
|
|
79
|
+
declare function textResponse(text: string, status?: number): EdgeResponse;
|
|
80
|
+
/**
|
|
81
|
+
* 创建 HTML 响应
|
|
82
|
+
*/
|
|
83
|
+
declare function htmlResponse(html: string, status?: number): EdgeResponse;
|
|
84
|
+
/**
|
|
85
|
+
* 创建重定向响应
|
|
86
|
+
*/
|
|
87
|
+
declare function redirectResponse(location: string, status?: number): EdgeResponse;
|
|
88
|
+
|
|
89
|
+
export { type EdgeCache, type EdgeCacheEntry, type EdgeCacheOptions, type EdgeContext, type EdgeHandler, type EdgeRequest, type EdgeResponse, type EdgeRoute, type EdgeRouter, type EdgeRouterOptions, createEdgeCache, createEdgeRouter, htmlResponse, jsonResponse, redirectResponse, textResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/runtime-edge - Type definitions
|
|
3
|
+
*/
|
|
4
|
+
interface EdgeRequest {
|
|
5
|
+
url: string;
|
|
6
|
+
method: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
body?: ReadableStream;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
interface EdgeResponse {
|
|
12
|
+
status: number;
|
|
13
|
+
statusText: string;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body?: ReadableStream;
|
|
16
|
+
}
|
|
17
|
+
interface EdgeContext {
|
|
18
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
19
|
+
passThroughOnException(): void;
|
|
20
|
+
}
|
|
21
|
+
interface EdgeHandler {
|
|
22
|
+
(request: EdgeRequest, context: EdgeContext): Promise<EdgeResponse> | EdgeResponse;
|
|
23
|
+
}
|
|
24
|
+
interface EdgeRouterOptions {
|
|
25
|
+
basePath?: string;
|
|
26
|
+
}
|
|
27
|
+
interface EdgeRoute {
|
|
28
|
+
path: string;
|
|
29
|
+
handler: EdgeHandler;
|
|
30
|
+
method: string;
|
|
31
|
+
}
|
|
32
|
+
interface EdgeRouter {
|
|
33
|
+
get(path: string, handler: EdgeHandler): void;
|
|
34
|
+
post(path: string, handler: EdgeHandler): void;
|
|
35
|
+
put(path: string, handler: EdgeHandler): void;
|
|
36
|
+
delete(path: string, handler: EdgeHandler): void;
|
|
37
|
+
patch(path: string, handler: EdgeHandler): void;
|
|
38
|
+
match(request: EdgeRequest): EdgeRoute | null;
|
|
39
|
+
handle(request: EdgeRequest, context?: EdgeContext): Promise<EdgeResponse>;
|
|
40
|
+
}
|
|
41
|
+
interface EdgeCacheOptions {
|
|
42
|
+
ttl?: number;
|
|
43
|
+
swr?: boolean;
|
|
44
|
+
staleWhileRevalidate?: number;
|
|
45
|
+
}
|
|
46
|
+
interface EdgeCacheEntry<T = unknown> {
|
|
47
|
+
value: T;
|
|
48
|
+
expires: number;
|
|
49
|
+
}
|
|
50
|
+
interface EdgeCache {
|
|
51
|
+
get<T>(key: string): Promise<T | null>;
|
|
52
|
+
set<T>(key: string, value: T, options?: EdgeCacheOptions): Promise<void>;
|
|
53
|
+
delete(key: string): Promise<void>;
|
|
54
|
+
clear(): Promise<void>;
|
|
55
|
+
has(key: string): Promise<boolean>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @lytjs/runtime-edge - LytJS edge runtime support
|
|
60
|
+
*
|
|
61
|
+
* Provides utilities for running LytJS in edge computing environments
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 创建内存边缘缓存
|
|
66
|
+
*/
|
|
67
|
+
declare function createEdgeCache(): EdgeCache;
|
|
68
|
+
/**
|
|
69
|
+
* 创建边缘路由器
|
|
70
|
+
*/
|
|
71
|
+
declare function createEdgeRouter(options?: EdgeRouterOptions): EdgeRouter;
|
|
72
|
+
/**
|
|
73
|
+
* 创建 JSON 响应
|
|
74
|
+
*/
|
|
75
|
+
declare function jsonResponse(data: unknown, status?: number): EdgeResponse;
|
|
76
|
+
/**
|
|
77
|
+
* 创建文本响应
|
|
78
|
+
*/
|
|
79
|
+
declare function textResponse(text: string, status?: number): EdgeResponse;
|
|
80
|
+
/**
|
|
81
|
+
* 创建 HTML 响应
|
|
82
|
+
*/
|
|
83
|
+
declare function htmlResponse(html: string, status?: number): EdgeResponse;
|
|
84
|
+
/**
|
|
85
|
+
* 创建重定向响应
|
|
86
|
+
*/
|
|
87
|
+
declare function redirectResponse(location: string, status?: number): EdgeResponse;
|
|
88
|
+
|
|
89
|
+
export { type EdgeCache, type EdgeCacheEntry, type EdgeCacheOptions, type EdgeContext, type EdgeHandler, type EdgeRequest, type EdgeResponse, type EdgeRoute, type EdgeRouter, type EdgeRouterOptions, createEdgeCache, createEdgeRouter, htmlResponse, jsonResponse, redirectResponse, textResponse };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function createEdgeCache() {
|
|
3
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4
|
+
return {
|
|
5
|
+
async get(key) {
|
|
6
|
+
const entry = cache.get(key);
|
|
7
|
+
if (!entry) return null;
|
|
8
|
+
if (entry.expires && Date.now() > entry.expires) {
|
|
9
|
+
cache.delete(key);
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return entry.value;
|
|
13
|
+
},
|
|
14
|
+
async set(key, value, options = {}) {
|
|
15
|
+
const ttl = options.ttl ?? 6e4;
|
|
16
|
+
const entry = {
|
|
17
|
+
value,
|
|
18
|
+
expires: Date.now() + ttl
|
|
19
|
+
};
|
|
20
|
+
cache.set(key, entry);
|
|
21
|
+
},
|
|
22
|
+
async delete(key) {
|
|
23
|
+
cache.delete(key);
|
|
24
|
+
},
|
|
25
|
+
async clear() {
|
|
26
|
+
cache.clear();
|
|
27
|
+
},
|
|
28
|
+
async has(key) {
|
|
29
|
+
const entry = cache.get(key);
|
|
30
|
+
if (!entry) return false;
|
|
31
|
+
if (entry.expires && Date.now() > entry.expires) {
|
|
32
|
+
cache.delete(key);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function createEdgeRouter(options = {}) {
|
|
40
|
+
const routes = [];
|
|
41
|
+
const basePath = options.basePath ?? "";
|
|
42
|
+
function addRoute(method, path, handler) {
|
|
43
|
+
const fullPath = basePath + path;
|
|
44
|
+
routes.push({ path: fullPath, handler, method });
|
|
45
|
+
}
|
|
46
|
+
function match(request) {
|
|
47
|
+
const url = new URL(request.url);
|
|
48
|
+
const path = url.pathname;
|
|
49
|
+
const method = request.method.toUpperCase();
|
|
50
|
+
for (const route of routes) {
|
|
51
|
+
if (route.method === method && route.path === path) {
|
|
52
|
+
return route;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
async function handle(request, context) {
|
|
58
|
+
const route = match(request);
|
|
59
|
+
if (!route) {
|
|
60
|
+
return {
|
|
61
|
+
status: 404,
|
|
62
|
+
statusText: "Not Found",
|
|
63
|
+
headers: { "Content-Type": "text/plain" }
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const response = await route.handler(
|
|
68
|
+
request,
|
|
69
|
+
context ?? {
|
|
70
|
+
waitUntil: () => {
|
|
71
|
+
},
|
|
72
|
+
passThroughOnException: () => {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
return response;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error("Edge handler error:", error);
|
|
79
|
+
return {
|
|
80
|
+
status: 500,
|
|
81
|
+
statusText: "Internal Server Error",
|
|
82
|
+
headers: { "Content-Type": "text/plain" }
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
get: (path, handler) => addRoute("GET", path, handler),
|
|
88
|
+
post: (path, handler) => addRoute("POST", path, handler),
|
|
89
|
+
put: (path, handler) => addRoute("PUT", path, handler),
|
|
90
|
+
delete: (path, handler) => addRoute("DELETE", path, handler),
|
|
91
|
+
patch: (path, handler) => addRoute("PATCH", path, handler),
|
|
92
|
+
match,
|
|
93
|
+
handle
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function jsonResponse(data, status = 200) {
|
|
97
|
+
return {
|
|
98
|
+
status,
|
|
99
|
+
statusText: "OK",
|
|
100
|
+
headers: { "Content-Type": "application/json" },
|
|
101
|
+
body: new ReadableStream({
|
|
102
|
+
start(controller) {
|
|
103
|
+
controller.enqueue(new TextEncoder().encode(JSON.stringify(data)));
|
|
104
|
+
controller.close();
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function textResponse(text, status = 200) {
|
|
110
|
+
return {
|
|
111
|
+
status,
|
|
112
|
+
statusText: "OK",
|
|
113
|
+
headers: { "Content-Type": "text/plain" },
|
|
114
|
+
body: new ReadableStream({
|
|
115
|
+
start(controller) {
|
|
116
|
+
controller.enqueue(new TextEncoder().encode(text));
|
|
117
|
+
controller.close();
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function htmlResponse(html, status = 200) {
|
|
123
|
+
return {
|
|
124
|
+
status,
|
|
125
|
+
statusText: "OK",
|
|
126
|
+
headers: { "Content-Type": "text/html" },
|
|
127
|
+
body: new ReadableStream({
|
|
128
|
+
start(controller) {
|
|
129
|
+
controller.enqueue(new TextEncoder().encode(html));
|
|
130
|
+
controller.close();
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function redirectResponse(location, status = 302) {
|
|
136
|
+
return {
|
|
137
|
+
status,
|
|
138
|
+
statusText: "Found",
|
|
139
|
+
headers: { Location: location }
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
createEdgeCache,
|
|
144
|
+
createEdgeRouter,
|
|
145
|
+
htmlResponse,
|
|
146
|
+
jsonResponse,
|
|
147
|
+
redirectResponse,
|
|
148
|
+
textResponse
|
|
149
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lytjs/runtime-edge",
|
|
3
|
+
"version": "6.5.0",
|
|
4
|
+
"description": "LytJS edge runtime support for serverless and edge computing environments",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"dev": "tsup --watch",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"type-check": "tsc --noEmit",
|
|
26
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
27
|
+
"clean": "rm -rf dist"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"tsup": "^8.0.0",
|
|
32
|
+
"typescript": "^5.4.0",
|
|
33
|
+
"vitest": "^3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://gitee.com/lytjs/lytjs.git",
|
|
39
|
+
"directory": "packages/ecosystem/packages/runtime-edge"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"lytjs",
|
|
43
|
+
"edge",
|
|
44
|
+
"serverless",
|
|
45
|
+
"runtime",
|
|
46
|
+
"edge-functions"
|
|
47
|
+
]
|
|
48
|
+
}
|