bxo 0.0.5-dev.43 → 0.0.5-dev.44
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/package.json +1 -1
- package/plugins/example.ts +173 -0
package/package.json
CHANGED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { Plugin } from '../index';
|
|
2
|
+
|
|
3
|
+
// Example 1: Simple logging plugin
|
|
4
|
+
export function logger(): Plugin {
|
|
5
|
+
return {
|
|
6
|
+
name: 'logger',
|
|
7
|
+
onRequest: async (ctx) => {
|
|
8
|
+
console.log(`[${new Date().toISOString()}] ${ctx.request.method} ${ctx.path}`);
|
|
9
|
+
},
|
|
10
|
+
onResponse: async (ctx, response) => {
|
|
11
|
+
if (response instanceof Response) {
|
|
12
|
+
console.log(`[${new Date().toISOString()}] ${ctx.request.method} ${ctx.path} - ${response.status}`);
|
|
13
|
+
}
|
|
14
|
+
return response;
|
|
15
|
+
},
|
|
16
|
+
onError: async (ctx, error) => {
|
|
17
|
+
console.error(`[${new Date().toISOString()}] Error in ${ctx.request.method} ${ctx.path}:`, error);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Example 2: Authentication plugin
|
|
23
|
+
export function auth(secret: string): Plugin {
|
|
24
|
+
return {
|
|
25
|
+
name: 'auth',
|
|
26
|
+
onRequest: async (ctx) => {
|
|
27
|
+
const token = ctx.headers.authorization?.replace('Bearer ', '');
|
|
28
|
+
|
|
29
|
+
if (!token) {
|
|
30
|
+
throw new Response(JSON.stringify({ error: 'No token provided' }), {
|
|
31
|
+
status: 401,
|
|
32
|
+
headers: { 'Content-Type': 'application/json' }
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Simple token validation (replace with your actual logic)
|
|
37
|
+
if (token !== secret) {
|
|
38
|
+
throw new Response(JSON.stringify({ error: 'Invalid token' }), {
|
|
39
|
+
status: 401,
|
|
40
|
+
headers: { 'Content-Type': 'application/json' }
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Add user info to context
|
|
45
|
+
(ctx as any).user = { id: 'user-123', token };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Example 3: Request timing plugin
|
|
51
|
+
export function timing(): Plugin {
|
|
52
|
+
return {
|
|
53
|
+
name: 'timing',
|
|
54
|
+
onRequest: async (ctx) => {
|
|
55
|
+
(ctx as any).startTime = Date.now();
|
|
56
|
+
},
|
|
57
|
+
onResponse: async (ctx, response) => {
|
|
58
|
+
const startTime = (ctx as any).startTime;
|
|
59
|
+
if (startTime) {
|
|
60
|
+
const duration = Date.now() - startTime;
|
|
61
|
+
console.log(`Request to ${ctx.path} took ${duration}ms`);
|
|
62
|
+
|
|
63
|
+
// Add timing header to response
|
|
64
|
+
if (response instanceof Response) {
|
|
65
|
+
const newResponse = new Response(response.body, {
|
|
66
|
+
status: response.status,
|
|
67
|
+
statusText: response.statusText,
|
|
68
|
+
headers: new Headers(response.headers)
|
|
69
|
+
});
|
|
70
|
+
newResponse.headers.set('X-Response-Time', `${duration}ms`);
|
|
71
|
+
return newResponse;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Example 4: Request ID plugin
|
|
80
|
+
export function requestId(): Plugin {
|
|
81
|
+
return {
|
|
82
|
+
name: 'requestId',
|
|
83
|
+
onRequest: async (ctx) => {
|
|
84
|
+
const requestId = crypto.randomUUID();
|
|
85
|
+
(ctx as any).requestId = requestId;
|
|
86
|
+
|
|
87
|
+
// Add request ID to response headers
|
|
88
|
+
ctx.set.headers = {
|
|
89
|
+
...ctx.set.headers,
|
|
90
|
+
'X-Request-ID': requestId
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Example 5: Conditional plugin (only applies to certain paths)
|
|
97
|
+
export function conditionalAuth(secret: string, paths: string[]): Plugin {
|
|
98
|
+
return {
|
|
99
|
+
name: 'conditionalAuth',
|
|
100
|
+
onRequest: async (ctx) => {
|
|
101
|
+
// Only apply auth to specified paths
|
|
102
|
+
if (!paths.some(path => ctx.path.startsWith(path))) {
|
|
103
|
+
return; // Skip authentication for this path
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const token = ctx.headers.authorization?.replace('Bearer ', '');
|
|
107
|
+
|
|
108
|
+
if (!token || token !== secret) {
|
|
109
|
+
throw new Response(JSON.stringify({ error: 'Authentication required' }), {
|
|
110
|
+
status: 401,
|
|
111
|
+
headers: { 'Content-Type': 'application/json' }
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Example 6: Response transformation plugin
|
|
119
|
+
export function responseTransformer(): Plugin {
|
|
120
|
+
return {
|
|
121
|
+
name: 'responseTransformer',
|
|
122
|
+
onResponse: async (ctx, response) => {
|
|
123
|
+
// Only transform JSON responses
|
|
124
|
+
if (response instanceof Response) {
|
|
125
|
+
const contentType = response.headers.get('content-type');
|
|
126
|
+
if (contentType?.includes('application/json')) {
|
|
127
|
+
try {
|
|
128
|
+
const data = await response.json();
|
|
129
|
+
|
|
130
|
+
// Transform the response data
|
|
131
|
+
const transformed = {
|
|
132
|
+
success: true,
|
|
133
|
+
data,
|
|
134
|
+
timestamp: new Date().toISOString(),
|
|
135
|
+
path: ctx.path
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return new Response(JSON.stringify(transformed), {
|
|
139
|
+
status: response.status,
|
|
140
|
+
headers: response.headers
|
|
141
|
+
});
|
|
142
|
+
} catch (error) {
|
|
143
|
+
// If response is not JSON, return as-is
|
|
144
|
+
return response;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return response;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Example 7: Error handling plugin
|
|
155
|
+
export function errorHandler(): Plugin {
|
|
156
|
+
return {
|
|
157
|
+
name: 'errorHandler',
|
|
158
|
+
onError: async (ctx, error) => {
|
|
159
|
+
console.error(`Error in ${ctx.request.method} ${ctx.path}:`, error);
|
|
160
|
+
|
|
161
|
+
// Return a standardized error response
|
|
162
|
+
return new Response(JSON.stringify({
|
|
163
|
+
error: 'Internal Server Error',
|
|
164
|
+
message: error.message,
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
path: ctx.path
|
|
167
|
+
}), {
|
|
168
|
+
status: 500,
|
|
169
|
+
headers: { 'Content-Type': 'application/json' }
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|