@wxn0brp/falcon-frame 0.0.6 → 0.0.7
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/plugins/cors.d.ts +7 -0
- package/dist/plugins/cors.js +25 -0
- package/dist/plugins/rateLimit.d.ts +2 -0
- package/dist/plugins/rateLimit.js +23 -0
- package/dist/plugins.d.ts +8 -7
- package/dist/plugins.js +27 -15
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function createCORSPlugin(allowedOrigins, opts = {}) {
|
|
2
|
+
opts = {
|
|
3
|
+
accessControlAllowMethods: true,
|
|
4
|
+
accessControlAllowHeaders: true,
|
|
5
|
+
...opts,
|
|
6
|
+
};
|
|
7
|
+
return {
|
|
8
|
+
id: "cors",
|
|
9
|
+
process: (req, res, next) => {
|
|
10
|
+
const origin = req.headers.origin;
|
|
11
|
+
if (origin && allowedOrigins.includes(origin)) {
|
|
12
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
13
|
+
if (opts.accessControlAllowMethods)
|
|
14
|
+
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
|
15
|
+
if (opts.accessControlAllowHeaders)
|
|
16
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
17
|
+
}
|
|
18
|
+
if (req.method === "OPTIONS") {
|
|
19
|
+
res.statusCode = 204;
|
|
20
|
+
return res.end();
|
|
21
|
+
}
|
|
22
|
+
next();
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function createRateLimiterPlugin(maxRequests, windowMs) {
|
|
2
|
+
const rateLimitMap = new Map();
|
|
3
|
+
return {
|
|
4
|
+
id: "rateLimiter",
|
|
5
|
+
process: (req, res, next) => {
|
|
6
|
+
const ip = req.socket.remoteAddress ?? "unknown";
|
|
7
|
+
const now = Date.now();
|
|
8
|
+
const record = rateLimitMap.get(ip);
|
|
9
|
+
if (!record || now - record.lastRequest > windowMs) {
|
|
10
|
+
rateLimitMap.set(ip, { count: 1, lastRequest: now });
|
|
11
|
+
return next();
|
|
12
|
+
}
|
|
13
|
+
if (record.count >= maxRequests) {
|
|
14
|
+
res.statusCode = 429;
|
|
15
|
+
return res.end("Too Many Requests");
|
|
16
|
+
}
|
|
17
|
+
record.count++;
|
|
18
|
+
record.lastRequest = now;
|
|
19
|
+
rateLimitMap.set(ip, record);
|
|
20
|
+
next();
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
package/dist/plugins.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { RouteHandler } from "./types.js";
|
|
2
|
-
type PluginId = string;
|
|
3
|
-
interface Plugin {
|
|
2
|
+
export type PluginId = string;
|
|
3
|
+
export interface Plugin {
|
|
4
4
|
id: PluginId;
|
|
5
5
|
process: RouteHandler;
|
|
6
6
|
priority?: number;
|
|
7
7
|
}
|
|
8
|
+
export interface PluginOptions {
|
|
9
|
+
before?: PluginId | PluginId[];
|
|
10
|
+
after?: PluginId | PluginId[];
|
|
11
|
+
optional?: boolean;
|
|
12
|
+
}
|
|
8
13
|
export declare class PluginSystem {
|
|
9
14
|
private plugins;
|
|
10
15
|
private executionOrder;
|
|
@@ -13,10 +18,7 @@ export declare class PluginSystem {
|
|
|
13
18
|
* @param plugin - Plugin to register
|
|
14
19
|
* @param options - Options for positioning plugins
|
|
15
20
|
*/
|
|
16
|
-
register(plugin: Plugin, options?:
|
|
17
|
-
before?: PluginId;
|
|
18
|
-
after?: PluginId;
|
|
19
|
-
}): void;
|
|
21
|
+
register(plugin: Plugin, options?: PluginOptions): void;
|
|
20
22
|
/**
|
|
21
23
|
* Updates the execution order of plugins
|
|
22
24
|
* @param pluginId - ID of the plugin to position
|
|
@@ -40,4 +42,3 @@ export declare class PluginSystem {
|
|
|
40
42
|
*/
|
|
41
43
|
getPluginsInOrder(): Plugin[];
|
|
42
44
|
}
|
|
43
|
-
export {};
|
package/dist/plugins.js
CHANGED
|
@@ -21,25 +21,37 @@ export class PluginSystem {
|
|
|
21
21
|
* @param options - Options for positioning
|
|
22
22
|
*/
|
|
23
23
|
updateExecutionOrder(pluginId, options) {
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
if (this.executionOrder.includes(pluginId))
|
|
25
|
+
return;
|
|
26
|
+
const resolveTarget = (target) => {
|
|
27
|
+
if (!target)
|
|
28
|
+
return null;
|
|
29
|
+
const list = Array.isArray(target) ? target : [target];
|
|
30
|
+
return list.find(id => this.executionOrder.includes(id)) || null;
|
|
31
|
+
};
|
|
32
|
+
const beforeTarget = resolveTarget(options?.before);
|
|
33
|
+
const afterTarget = resolveTarget(options?.after);
|
|
34
|
+
if (beforeTarget) {
|
|
35
|
+
const index = this.executionOrder.indexOf(beforeTarget);
|
|
36
|
+
this.executionOrder.splice(index, 0, pluginId);
|
|
37
|
+
}
|
|
38
|
+
else if (afterTarget) {
|
|
39
|
+
const index = this.executionOrder.indexOf(afterTarget);
|
|
40
|
+
this.executionOrder.splice(index + 1, 0, pluginId);
|
|
41
|
+
}
|
|
42
|
+
else if (options?.before || options?.after) {
|
|
43
|
+
if (options.optional) {
|
|
44
|
+
this.executionOrder.push(pluginId); // fallback: add to the end
|
|
38
45
|
}
|
|
39
46
|
else {
|
|
40
|
-
|
|
47
|
+
throw new Error(`Plugin dependency not found for '${pluginId}': ` +
|
|
48
|
+
`before=${JSON.stringify(options?.before)}, ` +
|
|
49
|
+
`after=${JSON.stringify(options?.after)}`);
|
|
41
50
|
}
|
|
42
51
|
}
|
|
52
|
+
else {
|
|
53
|
+
this.executionOrder.push(pluginId);
|
|
54
|
+
}
|
|
43
55
|
}
|
|
44
56
|
/**
|
|
45
57
|
* Returns a RouteHandler that executes all registered plugins in the correct order
|