@guardcore/fastify 1.0.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/dist/index.cjs ADDED
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BaseSecurityDecorator: () => import_core2.BaseSecurityDecorator,
34
+ BehaviorRule: () => import_core2.BehaviorRule,
35
+ FastifyGuardRequest: () => FastifyGuardRequest,
36
+ FastifyGuardResponse: () => FastifyGuardResponse,
37
+ FastifyResponseFactory: () => FastifyResponseFactory,
38
+ RouteConfig: () => import_core2.RouteConfig,
39
+ SecurityConfigSchema: () => import_core2.SecurityConfigSchema,
40
+ SecurityDecorator: () => import_core2.SecurityDecorator,
41
+ configureCors: () => configureCors,
42
+ defaultLogger: () => import_core2.defaultLogger,
43
+ guardPlugin: () => guardPlugin
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/plugin.ts
48
+ var import_core = require("@guardcore/core");
49
+
50
+ // src/adapters.ts
51
+ var FastifyGuardRequest = class {
52
+ constructor(req) {
53
+ this.req = req;
54
+ }
55
+ _state = {};
56
+ get urlPath() {
57
+ return this.req.url.split("?")[0];
58
+ }
59
+ get urlScheme() {
60
+ return this.req.protocol;
61
+ }
62
+ get urlFull() {
63
+ return `${this.req.protocol}://${this.req.hostname}${this.req.url}`;
64
+ }
65
+ urlReplaceScheme(scheme) {
66
+ return this.urlFull.replace(/^https?/, scheme);
67
+ }
68
+ get method() {
69
+ return this.req.method;
70
+ }
71
+ get clientHost() {
72
+ return this.req.ip ?? null;
73
+ }
74
+ get headers() {
75
+ return this.req.headers;
76
+ }
77
+ get queryParams() {
78
+ return this.req.query ?? {};
79
+ }
80
+ async body() {
81
+ const raw = this.req.body;
82
+ if (raw instanceof Buffer) return new Uint8Array(raw);
83
+ if (typeof raw === "string") return new TextEncoder().encode(raw);
84
+ if (raw !== void 0 && raw !== null) return new TextEncoder().encode(JSON.stringify(raw));
85
+ return new Uint8Array(0);
86
+ }
87
+ get state() {
88
+ return this._state;
89
+ }
90
+ get scope() {
91
+ return {};
92
+ }
93
+ };
94
+ var FastifyGuardResponse = class {
95
+ constructor(statusCode, content) {
96
+ this.statusCode = statusCode;
97
+ this._body = new TextEncoder().encode(content);
98
+ this._headers["content-type"] = "application/json";
99
+ }
100
+ _headers = {};
101
+ _body;
102
+ get headers() {
103
+ return this._headers;
104
+ }
105
+ setHeader(name, value) {
106
+ this._headers[name] = value;
107
+ }
108
+ get body() {
109
+ return this._body;
110
+ }
111
+ get bodyText() {
112
+ return this._body ? new TextDecoder().decode(this._body) : null;
113
+ }
114
+ };
115
+ var FastifyResponseFactory = class {
116
+ createResponse(content, statusCode) {
117
+ return new FastifyGuardResponse(statusCode, JSON.stringify({ detail: content }));
118
+ }
119
+ createRedirectResponse(url, statusCode) {
120
+ const resp = new FastifyGuardResponse(statusCode, "");
121
+ resp.setHeader("location", url);
122
+ return resp;
123
+ }
124
+ };
125
+
126
+ // src/plugin.ts
127
+ async function guardPlugin(fastify, options) {
128
+ const resolved = import_core.SecurityConfigSchema.parse(options.config);
129
+ const logger = resolved.logger ?? import_core.defaultLogger;
130
+ const responseFactory = new FastifyResponseFactory();
131
+ const components = await (0, import_core.initializeSecurityMiddleware)(
132
+ resolved,
133
+ logger,
134
+ responseFactory,
135
+ options.agentHandler,
136
+ options.geoIpHandler,
137
+ options.guardDecorator
138
+ );
139
+ logger.info("Guard security plugin initialized");
140
+ fastify.addHook("onRequest", async (request, reply) => {
141
+ const guardReq = new FastifyGuardRequest(request);
142
+ const passthrough = await components.bypassHandler.handlePassthrough(
143
+ guardReq,
144
+ async () => createPassthroughResponse()
145
+ );
146
+ if (passthrough) {
147
+ sendFastifyResponse(reply, passthrough);
148
+ return;
149
+ }
150
+ const routeConfig = components.routeResolver.getRouteConfig(guardReq);
151
+ const bypass = await components.bypassHandler.handleSecurityBypass(
152
+ guardReq,
153
+ async () => createPassthroughResponse(),
154
+ routeConfig
155
+ );
156
+ if (bypass) {
157
+ sendFastifyResponse(reply, bypass);
158
+ return;
159
+ }
160
+ const blockResponse = await components.pipeline.execute(guardReq);
161
+ if (blockResponse) {
162
+ sendFastifyResponse(reply, blockResponse);
163
+ return;
164
+ }
165
+ if (routeConfig && routeConfig.behaviorRules.length > 0) {
166
+ const clientIp = guardReq.clientHost ?? "unknown";
167
+ await components.behavioralProcessor.processUsageRules(guardReq, clientIp, routeConfig);
168
+ }
169
+ request["_guardRequest"] = guardReq;
170
+ request["_guardRouteConfig"] = routeConfig;
171
+ request["_guardStartTime"] = performance.now();
172
+ });
173
+ fastify.addHook("onSend", async (request, reply, payload) => {
174
+ const guardReq = request["_guardRequest"];
175
+ const routeConfig = request["_guardRouteConfig"];
176
+ const startTime = request["_guardStartTime"];
177
+ if (!guardReq || startTime === void 0) return payload;
178
+ const responseTime = (performance.now() - startTime) / 1e3;
179
+ const bodyText = typeof payload === "string" ? payload : null;
180
+ const capturedResponse = {
181
+ statusCode: reply.statusCode,
182
+ headers: Object.fromEntries(
183
+ Object.entries(reply.getHeaders()).map(([k, v]) => [k, String(v)])
184
+ ),
185
+ setHeader(name, value) {
186
+ reply.header(name, value);
187
+ },
188
+ body: bodyText ? new TextEncoder().encode(bodyText) : null,
189
+ bodyText
190
+ };
191
+ await components.errorResponseFactory.processResponse(
192
+ guardReq,
193
+ capturedResponse,
194
+ responseTime,
195
+ routeConfig ?? null,
196
+ routeConfig ? async (req, res, clientIp, rc) => {
197
+ await components.behavioralProcessor.processReturnRules(req, res, clientIp, rc);
198
+ } : void 0
199
+ );
200
+ return payload;
201
+ });
202
+ }
203
+ function sendFastifyResponse(reply, response) {
204
+ for (const [name, value] of Object.entries(response.headers)) {
205
+ reply.header(name, value);
206
+ }
207
+ if (response.headers["location"]) {
208
+ reply.redirect(response.headers["location"]);
209
+ return;
210
+ }
211
+ reply.status(response.statusCode).send(response.bodyText ?? "");
212
+ }
213
+ function createPassthroughResponse() {
214
+ return { statusCode: 200, headers: {}, setHeader() {
215
+ }, body: null, bodyText: null };
216
+ }
217
+
218
+ // src/cors.ts
219
+ async function configureCors(fastify, config) {
220
+ if (!config.enableCors) return;
221
+ try {
222
+ const fastifyCors = await import("@fastify/cors");
223
+ await fastify.register(fastifyCors.default ?? fastifyCors, {
224
+ origin: config.corsAllowOrigins,
225
+ methods: config.corsAllowMethods,
226
+ allowedHeaders: config.corsAllowHeaders,
227
+ credentials: config.corsAllowCredentials,
228
+ exposedHeaders: config.corsExposeHeaders,
229
+ maxAge: config.corsMaxAge
230
+ });
231
+ } catch {
232
+ throw new Error(
233
+ '@guardcore/fastify: CORS is enabled but "@fastify/cors" is not installed. Run: pnpm add @fastify/cors'
234
+ );
235
+ }
236
+ }
237
+
238
+ // src/index.ts
239
+ var import_core2 = require("@guardcore/core");
240
+ // Annotate the CommonJS export names for ESM import in node:
241
+ 0 && (module.exports = {
242
+ BaseSecurityDecorator,
243
+ BehaviorRule,
244
+ FastifyGuardRequest,
245
+ FastifyGuardResponse,
246
+ FastifyResponseFactory,
247
+ RouteConfig,
248
+ SecurityConfigSchema,
249
+ SecurityDecorator,
250
+ configureCors,
251
+ defaultLogger,
252
+ guardPlugin
253
+ });
254
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/adapters.ts","../src/cors.ts"],"sourcesContent":["export { guardPlugin } from './plugin.js';\nexport type { GuardPluginOptions } from './plugin.js';\nexport { configureCors } from './cors.js';\nexport { FastifyGuardRequest, FastifyGuardResponse, FastifyResponseFactory } from './adapters.js';\n\nexport {\n SecurityConfigSchema,\n BaseSecurityDecorator,\n SecurityDecorator,\n RouteConfig,\n BehaviorRule,\n defaultLogger,\n} from '@guardcore/core';\n\nexport type {\n SecurityConfig,\n ResolvedSecurityConfig,\n GuardRequest,\n GuardResponse,\n Logger,\n} from '@guardcore/core';\n","import type { FastifyInstance, FastifyReply } from 'fastify';\nimport type {\n SecurityConfig,\n GuardRequest,\n GuardResponse,\n Logger,\n AgentHandlerProtocol,\n GeoIPHandler,\n SecurityMiddlewareComponents,\n RouteConfig,\n} from '@guardcore/core';\nimport { SecurityConfigSchema, defaultLogger, initializeSecurityMiddleware } from '@guardcore/core';\nimport { FastifyGuardRequest, FastifyResponseFactory } from './adapters.js';\n\nexport interface GuardPluginOptions {\n config: SecurityConfig;\n agentHandler?: AgentHandlerProtocol;\n geoIpHandler?: GeoIPHandler;\n guardDecorator?: unknown;\n}\n\nexport async function guardPlugin(fastify: FastifyInstance, options: GuardPluginOptions): Promise<void> {\n const resolved = SecurityConfigSchema.parse(options.config);\n const logger: Logger = resolved.logger ?? defaultLogger;\n const responseFactory = new FastifyResponseFactory();\n\n const components: SecurityMiddlewareComponents = await initializeSecurityMiddleware(\n resolved, logger, responseFactory,\n options.agentHandler, options.geoIpHandler, options.guardDecorator,\n );\n\n logger.info('Guard security plugin initialized');\n\n fastify.addHook('onRequest', async (request, reply) => {\n const guardReq = new FastifyGuardRequest(request);\n\n const passthrough = await components.bypassHandler.handlePassthrough(\n guardReq, async () => createPassthroughResponse(),\n );\n if (passthrough) {\n sendFastifyResponse(reply, passthrough);\n return;\n }\n\n const routeConfig = components.routeResolver.getRouteConfig(guardReq);\n\n const bypass = await components.bypassHandler.handleSecurityBypass(\n guardReq, async () => createPassthroughResponse(), routeConfig,\n );\n if (bypass) {\n sendFastifyResponse(reply, bypass);\n return;\n }\n\n const blockResponse = await components.pipeline.execute(guardReq);\n if (blockResponse) {\n sendFastifyResponse(reply, blockResponse);\n return;\n }\n\n if (routeConfig && routeConfig.behaviorRules.length > 0) {\n const clientIp = guardReq.clientHost ?? 'unknown';\n await components.behavioralProcessor.processUsageRules(guardReq, clientIp, routeConfig);\n }\n\n (request as unknown as Record<string, unknown>)['_guardRequest'] = guardReq;\n (request as unknown as Record<string, unknown>)['_guardRouteConfig'] = routeConfig;\n (request as unknown as Record<string, unknown>)['_guardStartTime'] = performance.now();\n });\n\n fastify.addHook('onSend', async (request, reply, payload) => {\n const guardReq = (request as unknown as Record<string, unknown>)['_guardRequest'] as FastifyGuardRequest | undefined;\n const routeConfig = (request as unknown as Record<string, unknown>)['_guardRouteConfig'] as RouteConfig | null | undefined;\n const startTime = (request as unknown as Record<string, unknown>)['_guardStartTime'] as number | undefined;\n\n if (!guardReq || startTime === undefined) return payload;\n\n const responseTime = (performance.now() - startTime) / 1000;\n const bodyText = typeof payload === 'string' ? payload : null;\n const capturedResponse: GuardResponse = {\n statusCode: reply.statusCode,\n headers: Object.fromEntries(\n Object.entries(reply.getHeaders()).map(([k, v]) => [k, String(v)]),\n ),\n setHeader(name: string, value: string) { reply.header(name, value); },\n body: bodyText ? new TextEncoder().encode(bodyText) : null,\n bodyText,\n };\n\n await components.errorResponseFactory.processResponse(\n guardReq, capturedResponse, responseTime, routeConfig ?? null,\n routeConfig ? async (req: GuardRequest, res: GuardResponse, clientIp: string, rc: RouteConfig) => {\n await components.behavioralProcessor.processReturnRules(req, res, clientIp, rc);\n } : undefined,\n );\n\n return payload;\n });\n}\n\nfunction sendFastifyResponse(reply: FastifyReply, response: GuardResponse): void {\n for (const [name, value] of Object.entries(response.headers)) {\n reply.header(name, value);\n }\n\n if (response.headers['location']) {\n reply.redirect(response.headers['location']);\n return;\n }\n\n reply.status(response.statusCode).send(response.bodyText ?? '');\n}\n\nfunction createPassthroughResponse(): GuardResponse {\n return { statusCode: 200, headers: {}, setHeader() {}, body: null, bodyText: null };\n}\n","import type { FastifyRequest } from 'fastify';\nimport type { GuardRequest, GuardRequestState, GuardResponse, GuardResponseFactory } from '@guardcore/core';\n\nexport class FastifyGuardRequest implements GuardRequest {\n private _state: GuardRequestState = {};\n\n constructor(private readonly req: FastifyRequest) {}\n\n get urlPath(): string { return this.req.url.split('?')[0]; }\n get urlScheme(): string { return this.req.protocol; }\n get urlFull(): string { return `${this.req.protocol}://${this.req.hostname}${this.req.url}`; }\n urlReplaceScheme(scheme: string): string { return this.urlFull.replace(/^https?/, scheme); }\n get method(): string { return this.req.method; }\n get clientHost(): string | null { return this.req.ip ?? null; }\n get headers(): Readonly<Record<string, string>> { return this.req.headers as Record<string, string>; }\n get queryParams(): Readonly<Record<string, string>> { return (this.req.query ?? {}) as Record<string, string>; }\n async body(): Promise<Uint8Array> {\n const raw = this.req.body;\n if (raw instanceof Buffer) return new Uint8Array(raw);\n if (typeof raw === 'string') return new TextEncoder().encode(raw);\n if (raw !== undefined && raw !== null) return new TextEncoder().encode(JSON.stringify(raw));\n return new Uint8Array(0);\n }\n get state(): GuardRequestState { return this._state; }\n get scope(): Readonly<Record<string, unknown>> { return {}; }\n}\n\nexport class FastifyGuardResponse implements GuardResponse {\n private _headers: Record<string, string> = {};\n private _body: Uint8Array | null;\n\n constructor(readonly statusCode: number, content: string) {\n this._body = new TextEncoder().encode(content);\n this._headers['content-type'] = 'application/json';\n }\n\n get headers(): Record<string, string> { return this._headers; }\n setHeader(name: string, value: string): void { this._headers[name] = value; }\n get body(): Uint8Array | null { return this._body; }\n get bodyText(): string | null { return this._body ? new TextDecoder().decode(this._body) : null; }\n}\n\nexport class FastifyResponseFactory implements GuardResponseFactory {\n createResponse(content: string, statusCode: number): GuardResponse {\n return new FastifyGuardResponse(statusCode, JSON.stringify({ detail: content }));\n }\n\n createRedirectResponse(url: string, statusCode: number): GuardResponse {\n const resp = new FastifyGuardResponse(statusCode, '');\n resp.setHeader('location', url);\n return resp;\n }\n}\n","import type { FastifyInstance } from 'fastify';\nimport type { ResolvedSecurityConfig } from '@guardcore/core';\n\nexport async function configureCors(fastify: FastifyInstance, config: ResolvedSecurityConfig): Promise<void> {\n if (!config.enableCors) return;\n\n try {\n const fastifyCors = await import('@fastify/cors');\n await fastify.register(fastifyCors.default ?? fastifyCors, {\n origin: config.corsAllowOrigins,\n methods: config.corsAllowMethods,\n allowedHeaders: config.corsAllowHeaders,\n credentials: config.corsAllowCredentials,\n exposedHeaders: config.corsExposeHeaders,\n maxAge: config.corsMaxAge,\n });\n } catch {\n throw new Error(\n '@guardcore/fastify: CORS is enabled but \"@fastify/cors\" is not installed. ' +\n 'Run: pnpm add @fastify/cors',\n );\n }\n}\n"],"mappings":"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","names":["import_core"]}
@@ -0,0 +1,46 @@
1
+ import { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import { SecurityConfig, AgentHandlerProtocol, GeoIPHandler, ResolvedSecurityConfig, GuardRequest, GuardRequestState, GuardResponse, GuardResponseFactory } from '@guardcore/core';
3
+ export { BaseSecurityDecorator, BehaviorRule, GuardRequest, GuardResponse, Logger, ResolvedSecurityConfig, RouteConfig, SecurityConfig, SecurityConfigSchema, SecurityDecorator, defaultLogger } from '@guardcore/core';
4
+
5
+ interface GuardPluginOptions {
6
+ config: SecurityConfig;
7
+ agentHandler?: AgentHandlerProtocol;
8
+ geoIpHandler?: GeoIPHandler;
9
+ guardDecorator?: unknown;
10
+ }
11
+ declare function guardPlugin(fastify: FastifyInstance, options: GuardPluginOptions): Promise<void>;
12
+
13
+ declare function configureCors(fastify: FastifyInstance, config: ResolvedSecurityConfig): Promise<void>;
14
+
15
+ declare class FastifyGuardRequest implements GuardRequest {
16
+ private readonly req;
17
+ private _state;
18
+ constructor(req: FastifyRequest);
19
+ get urlPath(): string;
20
+ get urlScheme(): string;
21
+ get urlFull(): string;
22
+ urlReplaceScheme(scheme: string): string;
23
+ get method(): string;
24
+ get clientHost(): string | null;
25
+ get headers(): Readonly<Record<string, string>>;
26
+ get queryParams(): Readonly<Record<string, string>>;
27
+ body(): Promise<Uint8Array>;
28
+ get state(): GuardRequestState;
29
+ get scope(): Readonly<Record<string, unknown>>;
30
+ }
31
+ declare class FastifyGuardResponse implements GuardResponse {
32
+ readonly statusCode: number;
33
+ private _headers;
34
+ private _body;
35
+ constructor(statusCode: number, content: string);
36
+ get headers(): Record<string, string>;
37
+ setHeader(name: string, value: string): void;
38
+ get body(): Uint8Array | null;
39
+ get bodyText(): string | null;
40
+ }
41
+ declare class FastifyResponseFactory implements GuardResponseFactory {
42
+ createResponse(content: string, statusCode: number): GuardResponse;
43
+ createRedirectResponse(url: string, statusCode: number): GuardResponse;
44
+ }
45
+
46
+ export { FastifyGuardRequest, FastifyGuardResponse, FastifyResponseFactory, type GuardPluginOptions, configureCors, guardPlugin };
@@ -0,0 +1,46 @@
1
+ import { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import { SecurityConfig, AgentHandlerProtocol, GeoIPHandler, ResolvedSecurityConfig, GuardRequest, GuardRequestState, GuardResponse, GuardResponseFactory } from '@guardcore/core';
3
+ export { BaseSecurityDecorator, BehaviorRule, GuardRequest, GuardResponse, Logger, ResolvedSecurityConfig, RouteConfig, SecurityConfig, SecurityConfigSchema, SecurityDecorator, defaultLogger } from '@guardcore/core';
4
+
5
+ interface GuardPluginOptions {
6
+ config: SecurityConfig;
7
+ agentHandler?: AgentHandlerProtocol;
8
+ geoIpHandler?: GeoIPHandler;
9
+ guardDecorator?: unknown;
10
+ }
11
+ declare function guardPlugin(fastify: FastifyInstance, options: GuardPluginOptions): Promise<void>;
12
+
13
+ declare function configureCors(fastify: FastifyInstance, config: ResolvedSecurityConfig): Promise<void>;
14
+
15
+ declare class FastifyGuardRequest implements GuardRequest {
16
+ private readonly req;
17
+ private _state;
18
+ constructor(req: FastifyRequest);
19
+ get urlPath(): string;
20
+ get urlScheme(): string;
21
+ get urlFull(): string;
22
+ urlReplaceScheme(scheme: string): string;
23
+ get method(): string;
24
+ get clientHost(): string | null;
25
+ get headers(): Readonly<Record<string, string>>;
26
+ get queryParams(): Readonly<Record<string, string>>;
27
+ body(): Promise<Uint8Array>;
28
+ get state(): GuardRequestState;
29
+ get scope(): Readonly<Record<string, unknown>>;
30
+ }
31
+ declare class FastifyGuardResponse implements GuardResponse {
32
+ readonly statusCode: number;
33
+ private _headers;
34
+ private _body;
35
+ constructor(statusCode: number, content: string);
36
+ get headers(): Record<string, string>;
37
+ setHeader(name: string, value: string): void;
38
+ get body(): Uint8Array | null;
39
+ get bodyText(): string | null;
40
+ }
41
+ declare class FastifyResponseFactory implements GuardResponseFactory {
42
+ createResponse(content: string, statusCode: number): GuardResponse;
43
+ createRedirectResponse(url: string, statusCode: number): GuardResponse;
44
+ }
45
+
46
+ export { FastifyGuardRequest, FastifyGuardResponse, FastifyResponseFactory, type GuardPluginOptions, configureCors, guardPlugin };
package/dist/index.js ADDED
@@ -0,0 +1,214 @@
1
+ // src/plugin.ts
2
+ import { SecurityConfigSchema, defaultLogger, initializeSecurityMiddleware } from "@guardcore/core";
3
+
4
+ // src/adapters.ts
5
+ var FastifyGuardRequest = class {
6
+ constructor(req) {
7
+ this.req = req;
8
+ }
9
+ _state = {};
10
+ get urlPath() {
11
+ return this.req.url.split("?")[0];
12
+ }
13
+ get urlScheme() {
14
+ return this.req.protocol;
15
+ }
16
+ get urlFull() {
17
+ return `${this.req.protocol}://${this.req.hostname}${this.req.url}`;
18
+ }
19
+ urlReplaceScheme(scheme) {
20
+ return this.urlFull.replace(/^https?/, scheme);
21
+ }
22
+ get method() {
23
+ return this.req.method;
24
+ }
25
+ get clientHost() {
26
+ return this.req.ip ?? null;
27
+ }
28
+ get headers() {
29
+ return this.req.headers;
30
+ }
31
+ get queryParams() {
32
+ return this.req.query ?? {};
33
+ }
34
+ async body() {
35
+ const raw = this.req.body;
36
+ if (raw instanceof Buffer) return new Uint8Array(raw);
37
+ if (typeof raw === "string") return new TextEncoder().encode(raw);
38
+ if (raw !== void 0 && raw !== null) return new TextEncoder().encode(JSON.stringify(raw));
39
+ return new Uint8Array(0);
40
+ }
41
+ get state() {
42
+ return this._state;
43
+ }
44
+ get scope() {
45
+ return {};
46
+ }
47
+ };
48
+ var FastifyGuardResponse = class {
49
+ constructor(statusCode, content) {
50
+ this.statusCode = statusCode;
51
+ this._body = new TextEncoder().encode(content);
52
+ this._headers["content-type"] = "application/json";
53
+ }
54
+ _headers = {};
55
+ _body;
56
+ get headers() {
57
+ return this._headers;
58
+ }
59
+ setHeader(name, value) {
60
+ this._headers[name] = value;
61
+ }
62
+ get body() {
63
+ return this._body;
64
+ }
65
+ get bodyText() {
66
+ return this._body ? new TextDecoder().decode(this._body) : null;
67
+ }
68
+ };
69
+ var FastifyResponseFactory = class {
70
+ createResponse(content, statusCode) {
71
+ return new FastifyGuardResponse(statusCode, JSON.stringify({ detail: content }));
72
+ }
73
+ createRedirectResponse(url, statusCode) {
74
+ const resp = new FastifyGuardResponse(statusCode, "");
75
+ resp.setHeader("location", url);
76
+ return resp;
77
+ }
78
+ };
79
+
80
+ // src/plugin.ts
81
+ async function guardPlugin(fastify, options) {
82
+ const resolved = SecurityConfigSchema.parse(options.config);
83
+ const logger = resolved.logger ?? defaultLogger;
84
+ const responseFactory = new FastifyResponseFactory();
85
+ const components = await initializeSecurityMiddleware(
86
+ resolved,
87
+ logger,
88
+ responseFactory,
89
+ options.agentHandler,
90
+ options.geoIpHandler,
91
+ options.guardDecorator
92
+ );
93
+ logger.info("Guard security plugin initialized");
94
+ fastify.addHook("onRequest", async (request, reply) => {
95
+ const guardReq = new FastifyGuardRequest(request);
96
+ const passthrough = await components.bypassHandler.handlePassthrough(
97
+ guardReq,
98
+ async () => createPassthroughResponse()
99
+ );
100
+ if (passthrough) {
101
+ sendFastifyResponse(reply, passthrough);
102
+ return;
103
+ }
104
+ const routeConfig = components.routeResolver.getRouteConfig(guardReq);
105
+ const bypass = await components.bypassHandler.handleSecurityBypass(
106
+ guardReq,
107
+ async () => createPassthroughResponse(),
108
+ routeConfig
109
+ );
110
+ if (bypass) {
111
+ sendFastifyResponse(reply, bypass);
112
+ return;
113
+ }
114
+ const blockResponse = await components.pipeline.execute(guardReq);
115
+ if (blockResponse) {
116
+ sendFastifyResponse(reply, blockResponse);
117
+ return;
118
+ }
119
+ if (routeConfig && routeConfig.behaviorRules.length > 0) {
120
+ const clientIp = guardReq.clientHost ?? "unknown";
121
+ await components.behavioralProcessor.processUsageRules(guardReq, clientIp, routeConfig);
122
+ }
123
+ request["_guardRequest"] = guardReq;
124
+ request["_guardRouteConfig"] = routeConfig;
125
+ request["_guardStartTime"] = performance.now();
126
+ });
127
+ fastify.addHook("onSend", async (request, reply, payload) => {
128
+ const guardReq = request["_guardRequest"];
129
+ const routeConfig = request["_guardRouteConfig"];
130
+ const startTime = request["_guardStartTime"];
131
+ if (!guardReq || startTime === void 0) return payload;
132
+ const responseTime = (performance.now() - startTime) / 1e3;
133
+ const bodyText = typeof payload === "string" ? payload : null;
134
+ const capturedResponse = {
135
+ statusCode: reply.statusCode,
136
+ headers: Object.fromEntries(
137
+ Object.entries(reply.getHeaders()).map(([k, v]) => [k, String(v)])
138
+ ),
139
+ setHeader(name, value) {
140
+ reply.header(name, value);
141
+ },
142
+ body: bodyText ? new TextEncoder().encode(bodyText) : null,
143
+ bodyText
144
+ };
145
+ await components.errorResponseFactory.processResponse(
146
+ guardReq,
147
+ capturedResponse,
148
+ responseTime,
149
+ routeConfig ?? null,
150
+ routeConfig ? async (req, res, clientIp, rc) => {
151
+ await components.behavioralProcessor.processReturnRules(req, res, clientIp, rc);
152
+ } : void 0
153
+ );
154
+ return payload;
155
+ });
156
+ }
157
+ function sendFastifyResponse(reply, response) {
158
+ for (const [name, value] of Object.entries(response.headers)) {
159
+ reply.header(name, value);
160
+ }
161
+ if (response.headers["location"]) {
162
+ reply.redirect(response.headers["location"]);
163
+ return;
164
+ }
165
+ reply.status(response.statusCode).send(response.bodyText ?? "");
166
+ }
167
+ function createPassthroughResponse() {
168
+ return { statusCode: 200, headers: {}, setHeader() {
169
+ }, body: null, bodyText: null };
170
+ }
171
+
172
+ // src/cors.ts
173
+ async function configureCors(fastify, config) {
174
+ if (!config.enableCors) return;
175
+ try {
176
+ const fastifyCors = await import("@fastify/cors");
177
+ await fastify.register(fastifyCors.default ?? fastifyCors, {
178
+ origin: config.corsAllowOrigins,
179
+ methods: config.corsAllowMethods,
180
+ allowedHeaders: config.corsAllowHeaders,
181
+ credentials: config.corsAllowCredentials,
182
+ exposedHeaders: config.corsExposeHeaders,
183
+ maxAge: config.corsMaxAge
184
+ });
185
+ } catch {
186
+ throw new Error(
187
+ '@guardcore/fastify: CORS is enabled but "@fastify/cors" is not installed. Run: pnpm add @fastify/cors'
188
+ );
189
+ }
190
+ }
191
+
192
+ // src/index.ts
193
+ import {
194
+ SecurityConfigSchema as SecurityConfigSchema2,
195
+ BaseSecurityDecorator,
196
+ SecurityDecorator,
197
+ RouteConfig,
198
+ BehaviorRule,
199
+ defaultLogger as defaultLogger2
200
+ } from "@guardcore/core";
201
+ export {
202
+ BaseSecurityDecorator,
203
+ BehaviorRule,
204
+ FastifyGuardRequest,
205
+ FastifyGuardResponse,
206
+ FastifyResponseFactory,
207
+ RouteConfig,
208
+ SecurityConfigSchema2 as SecurityConfigSchema,
209
+ SecurityDecorator,
210
+ configureCors,
211
+ defaultLogger2 as defaultLogger,
212
+ guardPlugin
213
+ };
214
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/adapters.ts","../src/cors.ts","../src/index.ts"],"sourcesContent":["import type { FastifyInstance, FastifyReply } from 'fastify';\nimport type {\n SecurityConfig,\n GuardRequest,\n GuardResponse,\n Logger,\n AgentHandlerProtocol,\n GeoIPHandler,\n SecurityMiddlewareComponents,\n RouteConfig,\n} from '@guardcore/core';\nimport { SecurityConfigSchema, defaultLogger, initializeSecurityMiddleware } from '@guardcore/core';\nimport { FastifyGuardRequest, FastifyResponseFactory } from './adapters.js';\n\nexport interface GuardPluginOptions {\n config: SecurityConfig;\n agentHandler?: AgentHandlerProtocol;\n geoIpHandler?: GeoIPHandler;\n guardDecorator?: unknown;\n}\n\nexport async function guardPlugin(fastify: FastifyInstance, options: GuardPluginOptions): Promise<void> {\n const resolved = SecurityConfigSchema.parse(options.config);\n const logger: Logger = resolved.logger ?? defaultLogger;\n const responseFactory = new FastifyResponseFactory();\n\n const components: SecurityMiddlewareComponents = await initializeSecurityMiddleware(\n resolved, logger, responseFactory,\n options.agentHandler, options.geoIpHandler, options.guardDecorator,\n );\n\n logger.info('Guard security plugin initialized');\n\n fastify.addHook('onRequest', async (request, reply) => {\n const guardReq = new FastifyGuardRequest(request);\n\n const passthrough = await components.bypassHandler.handlePassthrough(\n guardReq, async () => createPassthroughResponse(),\n );\n if (passthrough) {\n sendFastifyResponse(reply, passthrough);\n return;\n }\n\n const routeConfig = components.routeResolver.getRouteConfig(guardReq);\n\n const bypass = await components.bypassHandler.handleSecurityBypass(\n guardReq, async () => createPassthroughResponse(), routeConfig,\n );\n if (bypass) {\n sendFastifyResponse(reply, bypass);\n return;\n }\n\n const blockResponse = await components.pipeline.execute(guardReq);\n if (blockResponse) {\n sendFastifyResponse(reply, blockResponse);\n return;\n }\n\n if (routeConfig && routeConfig.behaviorRules.length > 0) {\n const clientIp = guardReq.clientHost ?? 'unknown';\n await components.behavioralProcessor.processUsageRules(guardReq, clientIp, routeConfig);\n }\n\n (request as unknown as Record<string, unknown>)['_guardRequest'] = guardReq;\n (request as unknown as Record<string, unknown>)['_guardRouteConfig'] = routeConfig;\n (request as unknown as Record<string, unknown>)['_guardStartTime'] = performance.now();\n });\n\n fastify.addHook('onSend', async (request, reply, payload) => {\n const guardReq = (request as unknown as Record<string, unknown>)['_guardRequest'] as FastifyGuardRequest | undefined;\n const routeConfig = (request as unknown as Record<string, unknown>)['_guardRouteConfig'] as RouteConfig | null | undefined;\n const startTime = (request as unknown as Record<string, unknown>)['_guardStartTime'] as number | undefined;\n\n if (!guardReq || startTime === undefined) return payload;\n\n const responseTime = (performance.now() - startTime) / 1000;\n const bodyText = typeof payload === 'string' ? payload : null;\n const capturedResponse: GuardResponse = {\n statusCode: reply.statusCode,\n headers: Object.fromEntries(\n Object.entries(reply.getHeaders()).map(([k, v]) => [k, String(v)]),\n ),\n setHeader(name: string, value: string) { reply.header(name, value); },\n body: bodyText ? new TextEncoder().encode(bodyText) : null,\n bodyText,\n };\n\n await components.errorResponseFactory.processResponse(\n guardReq, capturedResponse, responseTime, routeConfig ?? null,\n routeConfig ? async (req: GuardRequest, res: GuardResponse, clientIp: string, rc: RouteConfig) => {\n await components.behavioralProcessor.processReturnRules(req, res, clientIp, rc);\n } : undefined,\n );\n\n return payload;\n });\n}\n\nfunction sendFastifyResponse(reply: FastifyReply, response: GuardResponse): void {\n for (const [name, value] of Object.entries(response.headers)) {\n reply.header(name, value);\n }\n\n if (response.headers['location']) {\n reply.redirect(response.headers['location']);\n return;\n }\n\n reply.status(response.statusCode).send(response.bodyText ?? '');\n}\n\nfunction createPassthroughResponse(): GuardResponse {\n return { statusCode: 200, headers: {}, setHeader() {}, body: null, bodyText: null };\n}\n","import type { FastifyRequest } from 'fastify';\nimport type { GuardRequest, GuardRequestState, GuardResponse, GuardResponseFactory } from '@guardcore/core';\n\nexport class FastifyGuardRequest implements GuardRequest {\n private _state: GuardRequestState = {};\n\n constructor(private readonly req: FastifyRequest) {}\n\n get urlPath(): string { return this.req.url.split('?')[0]; }\n get urlScheme(): string { return this.req.protocol; }\n get urlFull(): string { return `${this.req.protocol}://${this.req.hostname}${this.req.url}`; }\n urlReplaceScheme(scheme: string): string { return this.urlFull.replace(/^https?/, scheme); }\n get method(): string { return this.req.method; }\n get clientHost(): string | null { return this.req.ip ?? null; }\n get headers(): Readonly<Record<string, string>> { return this.req.headers as Record<string, string>; }\n get queryParams(): Readonly<Record<string, string>> { return (this.req.query ?? {}) as Record<string, string>; }\n async body(): Promise<Uint8Array> {\n const raw = this.req.body;\n if (raw instanceof Buffer) return new Uint8Array(raw);\n if (typeof raw === 'string') return new TextEncoder().encode(raw);\n if (raw !== undefined && raw !== null) return new TextEncoder().encode(JSON.stringify(raw));\n return new Uint8Array(0);\n }\n get state(): GuardRequestState { return this._state; }\n get scope(): Readonly<Record<string, unknown>> { return {}; }\n}\n\nexport class FastifyGuardResponse implements GuardResponse {\n private _headers: Record<string, string> = {};\n private _body: Uint8Array | null;\n\n constructor(readonly statusCode: number, content: string) {\n this._body = new TextEncoder().encode(content);\n this._headers['content-type'] = 'application/json';\n }\n\n get headers(): Record<string, string> { return this._headers; }\n setHeader(name: string, value: string): void { this._headers[name] = value; }\n get body(): Uint8Array | null { return this._body; }\n get bodyText(): string | null { return this._body ? new TextDecoder().decode(this._body) : null; }\n}\n\nexport class FastifyResponseFactory implements GuardResponseFactory {\n createResponse(content: string, statusCode: number): GuardResponse {\n return new FastifyGuardResponse(statusCode, JSON.stringify({ detail: content }));\n }\n\n createRedirectResponse(url: string, statusCode: number): GuardResponse {\n const resp = new FastifyGuardResponse(statusCode, '');\n resp.setHeader('location', url);\n return resp;\n }\n}\n","import type { FastifyInstance } from 'fastify';\nimport type { ResolvedSecurityConfig } from '@guardcore/core';\n\nexport async function configureCors(fastify: FastifyInstance, config: ResolvedSecurityConfig): Promise<void> {\n if (!config.enableCors) return;\n\n try {\n const fastifyCors = await import('@fastify/cors');\n await fastify.register(fastifyCors.default ?? fastifyCors, {\n origin: config.corsAllowOrigins,\n methods: config.corsAllowMethods,\n allowedHeaders: config.corsAllowHeaders,\n credentials: config.corsAllowCredentials,\n exposedHeaders: config.corsExposeHeaders,\n maxAge: config.corsMaxAge,\n });\n } catch {\n throw new Error(\n '@guardcore/fastify: CORS is enabled but \"@fastify/cors\" is not installed. ' +\n 'Run: pnpm add @fastify/cors',\n );\n }\n}\n","export { guardPlugin } from './plugin.js';\nexport type { GuardPluginOptions } from './plugin.js';\nexport { configureCors } from './cors.js';\nexport { FastifyGuardRequest, FastifyGuardResponse, FastifyResponseFactory } from './adapters.js';\n\nexport {\n SecurityConfigSchema,\n BaseSecurityDecorator,\n SecurityDecorator,\n RouteConfig,\n BehaviorRule,\n defaultLogger,\n} from '@guardcore/core';\n\nexport type {\n SecurityConfig,\n ResolvedSecurityConfig,\n GuardRequest,\n GuardResponse,\n Logger,\n} from '@guardcore/core';\n"],"mappings":"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","names":["SecurityConfigSchema","defaultLogger"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@guardcore/fastify",
3
+ "version": "1.0.0",
4
+ "description": "Fastify adapter for @guardcore/core security middleware",
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",
21
+ "test": "vitest run",
22
+ "lint": "tsc --noEmit",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "dependencies": {
26
+ "@guardcore/core": "workspace:*"
27
+ },
28
+ "devDependencies": {
29
+ "tsup": "^8",
30
+ "vitest": "^4",
31
+ "typescript": "~5.9",
32
+ "fastify": "^5"
33
+ },
34
+ "peerDependencies": {
35
+ "fastify": "^5",
36
+ "@fastify/cors": "^9"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "@fastify/cors": {
40
+ "optional": true
41
+ }
42
+ },
43
+ "license": "MIT",
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/rennf93/guard-core-ts.git",
50
+ "directory": "packages/fastify"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ }
55
+ }