@noony-serverless/core 0.4.2 → 0.4.4
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/build/core/handler.d.ts +1 -1
- package/build/core/handler.js +12 -2
- package/build/middlewares/responseWrapperMiddleware.d.ts +3 -1
- package/build/middlewares/responseWrapperMiddleware.js +10 -5
- package/build/utils/fastify-wrapper.d.ts +11 -0
- package/build/utils/fastify-wrapper.js +44 -0
- package/package.json +1 -1
package/build/core/handler.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export declare class Handler<T = unknown, U = unknown> {
|
|
|
46
46
|
private middlewaresPrecomputed;
|
|
47
47
|
static use<T = unknown, U = unknown>(middleware: BaseMiddleware<T, U>): Handler<T, U>;
|
|
48
48
|
use<NewT = T, NewU = U>(middleware: BaseMiddleware<NewT, NewU>): Handler<NewT, NewU>;
|
|
49
|
-
handle(handler: (context: Context<T, U>) => Promise<void>): Handler<T, U>;
|
|
49
|
+
handle(handler: (context: Context<T, U>) => Promise<void | unknown>): Handler<T, U>;
|
|
50
50
|
/**
|
|
51
51
|
* Performance optimization: Pre-compute middleware arrays to avoid runtime array operations
|
|
52
52
|
*/
|
package/build/core/handler.js
CHANGED
|
@@ -74,7 +74,12 @@ class Handler {
|
|
|
74
74
|
try {
|
|
75
75
|
// Execute before middlewares with performance optimizations
|
|
76
76
|
await this.executeBeforeMiddlewares(context);
|
|
77
|
-
|
|
77
|
+
// Capture return value from handler
|
|
78
|
+
const returnValue = await this.handler(context);
|
|
79
|
+
// If handler returns a value and responseData hasn't been set, use the return value
|
|
80
|
+
if (returnValue !== undefined && !context.responseData) {
|
|
81
|
+
context.responseData = returnValue;
|
|
82
|
+
}
|
|
78
83
|
// Execute after middlewares in reverse order using pre-computed array
|
|
79
84
|
await this.executeAfterMiddlewares(context);
|
|
80
85
|
}
|
|
@@ -129,7 +134,12 @@ class Handler {
|
|
|
129
134
|
try {
|
|
130
135
|
// Execute before middlewares with performance optimizations
|
|
131
136
|
await this.executeBeforeMiddlewares(context);
|
|
132
|
-
|
|
137
|
+
// Capture return value from handler
|
|
138
|
+
const returnValue = await this.handler(context);
|
|
139
|
+
// If handler returns a value and responseData hasn't been set, use the return value
|
|
140
|
+
if (returnValue !== undefined && !context.responseData) {
|
|
141
|
+
context.responseData = returnValue;
|
|
142
|
+
}
|
|
133
143
|
// Execute after middlewares in reverse order using pre-computed array
|
|
134
144
|
await this.executeAfterMiddlewares(context);
|
|
135
145
|
}
|
|
@@ -63,6 +63,8 @@ import { Context } from '../core/core';
|
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
65
|
export declare class ResponseWrapperMiddleware<T = unknown, TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
66
|
+
private defaultStatusCode?;
|
|
67
|
+
constructor(defaultStatusCode?: number | undefined);
|
|
66
68
|
after(context: Context<TBody, TUser>): Promise<void>;
|
|
67
69
|
}
|
|
68
70
|
/**
|
|
@@ -122,7 +124,7 @@ export declare class ResponseWrapperMiddleware<T = unknown, TBody = unknown, TUs
|
|
|
122
124
|
* });
|
|
123
125
|
* ```
|
|
124
126
|
*/
|
|
125
|
-
export declare const responseWrapperMiddleware: <T = unknown, TBody = unknown, TUser = unknown>() => BaseMiddleware<TBody, TUser>;
|
|
127
|
+
export declare const responseWrapperMiddleware: <T = unknown, TBody = unknown, TUser = unknown>(defaultStatusCode?: number) => BaseMiddleware<TBody, TUser>;
|
|
126
128
|
/**
|
|
127
129
|
* Helper function to set response data in context for later wrapping.
|
|
128
130
|
* This function should be used in handlers when using ResponseWrapperMiddleware.
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.responseWrapperMiddleware = exports.ResponseWrapperMiddleware = void 0;
|
|
4
4
|
exports.setResponseData = setResponseData;
|
|
5
|
-
const wrapResponse = (context) => {
|
|
5
|
+
const wrapResponse = (context, defaultStatusCode) => {
|
|
6
6
|
if (!context.res.headersSent) {
|
|
7
|
-
|
|
7
|
+
// Use defaultStatusCode if provided, otherwise use context.res.statusCode, finally default to 200
|
|
8
|
+
const statusCode = defaultStatusCode || context.res.statusCode || 200;
|
|
8
9
|
const body = context.responseData;
|
|
9
10
|
context.res.status(statusCode).json({
|
|
10
11
|
success: true,
|
|
@@ -76,8 +77,12 @@ const wrapResponse = (context) => {
|
|
|
76
77
|
* ```
|
|
77
78
|
*/
|
|
78
79
|
class ResponseWrapperMiddleware {
|
|
80
|
+
defaultStatusCode;
|
|
81
|
+
constructor(defaultStatusCode) {
|
|
82
|
+
this.defaultStatusCode = defaultStatusCode;
|
|
83
|
+
}
|
|
79
84
|
async after(context) {
|
|
80
|
-
wrapResponse(context);
|
|
85
|
+
wrapResponse(context, this.defaultStatusCode);
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
88
|
exports.ResponseWrapperMiddleware = ResponseWrapperMiddleware;
|
|
@@ -138,9 +143,9 @@ exports.ResponseWrapperMiddleware = ResponseWrapperMiddleware;
|
|
|
138
143
|
* });
|
|
139
144
|
* ```
|
|
140
145
|
*/
|
|
141
|
-
const responseWrapperMiddleware = () => ({
|
|
146
|
+
const responseWrapperMiddleware = (defaultStatusCode) => ({
|
|
142
147
|
after: async (context) => {
|
|
143
|
-
wrapResponse(context);
|
|
148
|
+
wrapResponse(context, defaultStatusCode);
|
|
144
149
|
},
|
|
145
150
|
});
|
|
146
151
|
exports.responseWrapperMiddleware = responseWrapperMiddleware;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { FastifyRequest, FastifyReply } from 'fastify';
|
|
2
2
|
import { Handler } from '../core/handler';
|
|
3
3
|
export declare const requestBodyMap: WeakMap<any, FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>>;
|
|
4
|
+
export interface CloudFunctionRequest {
|
|
5
|
+
method?: string;
|
|
6
|
+
body?: unknown;
|
|
7
|
+
url?: string;
|
|
8
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
9
|
+
__rawBody?: string;
|
|
10
|
+
rawBody?: string | Buffer;
|
|
11
|
+
readableEnded?: boolean;
|
|
12
|
+
complete?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function extractAndStoreRequestBody(req: CloudFunctionRequest): void;
|
|
4
15
|
export declare function createFastifyHandler(noonyHandler: Handler<unknown>, functionName: string, initializeDependencies: () => Promise<void>): (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
5
16
|
//# sourceMappingURL=fastify-wrapper.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.requestBodyMap = void 0;
|
|
4
|
+
exports.extractAndStoreRequestBody = extractAndStoreRequestBody;
|
|
4
5
|
exports.createFastifyHandler = createFastifyHandler;
|
|
5
6
|
const logger_1 = require("../core/logger");
|
|
6
7
|
// Global WeakMap to store the original Fastify request for each GenericRequest
|
|
@@ -178,10 +179,49 @@ const INTERNAL_ERROR_RESPONSE = Object.freeze({
|
|
|
178
179
|
});
|
|
179
180
|
// Constant for performance-critical string comparison
|
|
180
181
|
const RESPONSE_SENT_MESSAGE = 'RESPONSE_SENT';
|
|
182
|
+
// Helper: Extract and store request body for later use
|
|
183
|
+
function extractAndStoreRequestBody(req) {
|
|
184
|
+
if (!['POST', 'PUT', 'PATCH'].includes(req.method || '')) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Check if already has __rawBody from previous processing
|
|
188
|
+
if (req.__rawBody) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const body = req.body;
|
|
192
|
+
if (!body)
|
|
193
|
+
return;
|
|
194
|
+
// Use safe JSON stringify to handle circular references
|
|
195
|
+
try {
|
|
196
|
+
req.__rawBody = typeof body === 'string' ? body : JSON.stringify(body);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
// If circular reference or other serialization error, skip storing __rawBody
|
|
200
|
+
if (process.env.NODE_ENV === 'development') {
|
|
201
|
+
logger_1.logger.debug('[helper] Failed to stringify body, skipping __rawBody storage', {
|
|
202
|
+
error: error instanceof Error ? error.message : String(error),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (process.env.NODE_ENV === 'development') {
|
|
208
|
+
logger_1.logger.debug('[helper] Extracted and stored __rawBody', {
|
|
209
|
+
bodyLength: req.__rawBody.length,
|
|
210
|
+
bodyType: typeof body,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
181
214
|
function createFastifyHandler(noonyHandler, functionName, initializeDependencies) {
|
|
182
215
|
// Pre-bind the error log prefix to avoid string concatenation in hot path
|
|
183
216
|
const errorLogPrefix = `${functionName} handler error`;
|
|
184
217
|
return async (req, reply) => {
|
|
218
|
+
const requestId = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
219
|
+
console.log(`[FASTIFY-WRAPPER] ${errorLogPrefix} called`, {
|
|
220
|
+
requestId,
|
|
221
|
+
url: req.url,
|
|
222
|
+
method: req.method,
|
|
223
|
+
timestamp: new Date().toISOString(),
|
|
224
|
+
});
|
|
185
225
|
try {
|
|
186
226
|
// Ensure dependencies are initialized
|
|
187
227
|
await initializeDependencies();
|
|
@@ -190,6 +230,10 @@ function createFastifyHandler(noonyHandler, functionName, initializeDependencies
|
|
|
190
230
|
const genericRes = adaptFastifyResponse(reply);
|
|
191
231
|
// Execute Noony handler with adapted request/response
|
|
192
232
|
await noonyHandler.executeGeneric(genericReq, genericRes);
|
|
233
|
+
console.log(`[FASTIFY-WRAPPER] ${errorLogPrefix} completed`, {
|
|
234
|
+
requestId,
|
|
235
|
+
timestamp: new Date().toISOString(),
|
|
236
|
+
});
|
|
193
237
|
}
|
|
194
238
|
catch (error) {
|
|
195
239
|
// Fast path: check RESPONSE_SENT first (most common error to ignore)
|
package/package.json
CHANGED