@webiny/handler 0.0.0-unstable.611c5af35e → 0.0.0-unstable.61c048f412

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.
Files changed (89) hide show
  1. package/Context.d.ts +18 -9
  2. package/Context.js +18 -17
  3. package/Context.js.map +1 -1
  4. package/PreHandler/IPreHandler.d.ts +9 -0
  5. package/PreHandler/IPreHandler.js +7 -0
  6. package/PreHandler/IPreHandler.js.map +1 -0
  7. package/PreHandler/IfNotOptionsRequest.d.ts +9 -0
  8. package/PreHandler/IfNotOptionsRequest.js +21 -0
  9. package/PreHandler/IfNotOptionsRequest.js.map +1 -0
  10. package/PreHandler/IfOptionsRequest.d.ts +9 -0
  11. package/PreHandler/IfOptionsRequest.js +21 -0
  12. package/PreHandler/IfOptionsRequest.js.map +1 -0
  13. package/PreHandler/PreHandler.d.ts +9 -0
  14. package/PreHandler/PreHandler.js +17 -0
  15. package/PreHandler/PreHandler.js.map +1 -0
  16. package/PreHandler/ProcessBeforeHandlerPlugins.d.ts +10 -0
  17. package/PreHandler/ProcessBeforeHandlerPlugins.js +24 -0
  18. package/PreHandler/ProcessBeforeHandlerPlugins.js.map +1 -0
  19. package/PreHandler/ProcessContextPlugins.d.ts +10 -0
  20. package/PreHandler/ProcessContextPlugins.js +24 -0
  21. package/PreHandler/ProcessContextPlugins.js.map +1 -0
  22. package/PreHandler/ProcessHandlerOnRequestPlugins.d.ts +10 -0
  23. package/PreHandler/ProcessHandlerOnRequestPlugins.js +26 -0
  24. package/PreHandler/ProcessHandlerOnRequestPlugins.js.map +1 -0
  25. package/PreHandler/SendEarlyOptionsResponse.d.ts +9 -0
  26. package/PreHandler/SendEarlyOptionsResponse.js +31 -0
  27. package/PreHandler/SendEarlyOptionsResponse.js.map +1 -0
  28. package/PreHandler/SetDefaultHeaders.d.ts +9 -0
  29. package/PreHandler/SetDefaultHeaders.js +57 -0
  30. package/PreHandler/SetDefaultHeaders.js.map +1 -0
  31. package/README.md +10 -14
  32. package/ResponseHeaders.d.ts +24 -0
  33. package/ResponseHeaders.js +39 -0
  34. package/ResponseHeaders.js.map +1 -0
  35. package/abstractions/Reply.d.ts +5 -0
  36. package/abstractions/Reply.js +4 -0
  37. package/abstractions/Reply.js.map +1 -0
  38. package/abstractions/Request.d.ts +5 -0
  39. package/abstractions/Request.js +4 -0
  40. package/abstractions/Request.js.map +1 -0
  41. package/fastify.d.ts +8 -5
  42. package/fastify.js +309 -133
  43. package/fastify.js.map +1 -1
  44. package/index.d.ts +17 -8
  45. package/index.js +19 -92
  46. package/index.js.map +1 -1
  47. package/package.json +16 -25
  48. package/plugins/BeforeHandlerPlugin.d.ts +1 -1
  49. package/plugins/BeforeHandlerPlugin.js +6 -15
  50. package/plugins/BeforeHandlerPlugin.js.map +1 -1
  51. package/plugins/EventPlugin.d.ts +3 -3
  52. package/plugins/EventPlugin.js +6 -16
  53. package/plugins/EventPlugin.js.map +1 -1
  54. package/plugins/HandlerErrorPlugin.d.ts +6 -3
  55. package/plugins/HandlerErrorPlugin.js +6 -15
  56. package/plugins/HandlerErrorPlugin.js.map +1 -1
  57. package/plugins/HandlerOnRequestPlugin.d.ts +21 -0
  58. package/plugins/HandlerOnRequestPlugin.js +24 -0
  59. package/plugins/HandlerOnRequestPlugin.js.map +1 -0
  60. package/plugins/HandlerResultPlugin.d.ts +1 -1
  61. package/plugins/HandlerResultPlugin.js +6 -15
  62. package/plugins/HandlerResultPlugin.js.map +1 -1
  63. package/plugins/ModifyFastifyPlugin.d.ts +13 -0
  64. package/plugins/ModifyFastifyPlugin.js +16 -0
  65. package/plugins/ModifyFastifyPlugin.js.map +1 -0
  66. package/plugins/ModifyResponseHeadersPlugin.d.ts +14 -0
  67. package/plugins/ModifyResponseHeadersPlugin.js +16 -0
  68. package/plugins/ModifyResponseHeadersPlugin.js.map +1 -0
  69. package/plugins/OnRequestResponseSendPlugin.d.ts +26 -0
  70. package/plugins/OnRequestResponseSendPlugin.js +31 -0
  71. package/plugins/OnRequestResponseSendPlugin.js.map +1 -0
  72. package/plugins/OnRequestTimeoutPlugin.d.ts +12 -0
  73. package/plugins/OnRequestTimeoutPlugin.js +16 -0
  74. package/plugins/OnRequestTimeoutPlugin.js.map +1 -0
  75. package/plugins/RoutePlugin.d.ts +2 -2
  76. package/plugins/RoutePlugin.js +6 -15
  77. package/plugins/RoutePlugin.js.map +1 -1
  78. package/stringifyError.d.ts +5 -0
  79. package/stringifyError.js +20 -0
  80. package/stringifyError.js.map +1 -0
  81. package/suppressPunycodeWarnings.d.ts +1 -0
  82. package/suppressPunycodeWarnings.js +10 -0
  83. package/suppressPunycodeWarnings.js.map +1 -0
  84. package/types.d.ts +14 -13
  85. package/types.js +2 -17
  86. package/types.js.map +1 -1
  87. package/middleware.d.ts +0 -4
  88. package/middleware.js +0 -45
  89. package/middleware.js.map +0 -1
@@ -0,0 +1,4 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+ export const Request = createAbstraction("Request");
3
+
4
+ //# sourceMappingURL=Request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createAbstraction","Request"],"sources":["Request.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { Request as IRequest } from \"~/types.js\";\n\nexport const Request = createAbstraction<IRequest>(\"Request\");\n\nexport namespace Request {\n export type Interface = IRequest;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,qBAAqB;AAGvD,OAAO,MAAMC,OAAO,GAAGD,iBAAiB,CAAW,SAAS,CAAC","ignoreList":[]}
package/fastify.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- /// <reference types="node" />
2
- import { PluginCollection } from "@webiny/plugins/types";
3
- import { FastifyServerOptions as ServerOptions } from "fastify";
1
+ import type { PluginCollection } from "@webiny/plugins/types.js";
2
+ import { PluginsContainer } from "@webiny/plugins/types.js";
3
+ import type { FastifyInstance, FastifyServerOptions as ServerOptions } from "fastify";
4
4
  export interface CreateHandlerParams {
5
- plugins: PluginCollection;
5
+ plugins: PluginCollection | PluginsContainer;
6
6
  options?: ServerOptions;
7
+ debug?: boolean;
7
8
  }
8
- export declare const createHandler: (params: CreateHandlerParams) => import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> & PromiseLike<import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>>;
9
+ export declare const createHandler: (params: CreateHandlerParams) => FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> & PromiseLike<FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>> & {
10
+ __linterBrands: "SafePromiseLike";
11
+ };
package/fastify.js CHANGED
@@ -1,56 +1,48 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.createHandler = void 0;
8
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
9
- var _fastify = _interopRequireDefault(require("fastify"));
10
- var _utils = require("@webiny/utils");
11
- var _Context = require("./Context");
12
- var _error = _interopRequireDefault(require("@webiny/error"));
13
- var _RoutePlugin = require("./plugins/RoutePlugin");
14
- var _handlerClient = require("@webiny/handler-client");
15
- var _cookie = _interopRequireDefault(require("@fastify/cookie"));
16
- var _middleware = require("./middleware");
17
- var _api = require("@webiny/api");
18
- var _BeforeHandlerPlugin = require("./plugins/BeforeHandlerPlugin");
19
- var _HandlerResultPlugin = require("./plugins/HandlerResultPlugin");
20
- var _HandlerErrorPlugin = require("./plugins/HandlerErrorPlugin");
21
- const DEFAULT_HEADERS = (0, _objectSpread2.default)({
22
- "Cache-Control": "no-store",
23
- "Content-Type": "application/json; charset=utf-8",
24
- "Access-Control-Allow-Origin": "*",
25
- "Access-Control-Allow-Headers": "*",
26
- "Access-Control-Allow-Methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH"
27
- }, (0, _utils.getWebinyVersionHeaders)());
28
- const getDefaultHeaders = routes => {
29
- /**
30
- * If we are accepting all headers, just output that one.
31
- */
32
- const keys = Object.keys(routes);
33
- const all = keys.every(key => routes[key].length > 0);
34
- if (all) {
35
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
36
- "Access-Control-Allow-Methods": "*"
37
- });
38
- }
39
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
40
- "Access-Control-Allow-Methods": keys.filter(key => {
41
- const type = key;
42
- if (!routes[type] || Array.isArray(routes[type]) === false) {
43
- return false;
44
- }
45
- return routes[type].length > 0;
46
- }).sort().join(",")
1
+ import { PluginsContainer } from "@webiny/plugins/types.js";
2
+ import fastify from "fastify";
3
+ import { middleware } from "@webiny/utils";
4
+ import { Context } from "./Context.js";
5
+ import WebinyError from "@webiny/error";
6
+ import { RoutePlugin } from "./plugins/RoutePlugin.js";
7
+ import { createHandlerClient } from "@webiny/handler-client";
8
+ import fastifyCookie from "@fastify/cookie";
9
+ import fastifyCompress from "@fastify/compress";
10
+ import { ContextPlugin } from "@webiny/api";
11
+ import { BeforeHandlerPlugin } from "./plugins/BeforeHandlerPlugin.js";
12
+ import { HandlerResultPlugin } from "./plugins/HandlerResultPlugin.js";
13
+ import { HandlerErrorPlugin } from "./plugins/HandlerErrorPlugin.js";
14
+ import { ModifyFastifyPlugin } from "./plugins/ModifyFastifyPlugin.js";
15
+ import { HandlerOnRequestPlugin } from "./plugins/HandlerOnRequestPlugin.js";
16
+ import { ResponseHeaders } from "./ResponseHeaders.js";
17
+ import { ModifyResponseHeadersPlugin } from "./plugins/ModifyResponseHeadersPlugin.js";
18
+ import { SetDefaultHeaders } from "./PreHandler/SetDefaultHeaders.js";
19
+ import { PreHandler } from "./PreHandler/PreHandler.js";
20
+ import { stringifyError } from "./stringifyError.js";
21
+ import { ProcessHandlerOnRequestPlugins } from "./PreHandler/ProcessHandlerOnRequestPlugins.js";
22
+ import { ProcessContextPlugins } from "./PreHandler/ProcessContextPlugins.js";
23
+ import { IfNotOptionsRequest } from "./PreHandler/IfNotOptionsRequest.js";
24
+ import { ProcessBeforeHandlerPlugins } from "./PreHandler/ProcessBeforeHandlerPlugins.js";
25
+ import { IfOptionsRequest } from "./PreHandler/IfOptionsRequest.js";
26
+ import { SendEarlyOptionsResponse } from "./PreHandler/SendEarlyOptionsResponse.js";
27
+ import { OnRequestTimeoutPlugin } from "./plugins/OnRequestTimeoutPlugin.js";
28
+ import { OnRequestResponseSendPlugin } from "./plugins/OnRequestResponseSendPlugin.js";
29
+ import { Request } from "./abstractions/Request.js";
30
+ import { Reply } from "./abstractions/Reply.js";
31
+ const modifyResponseHeaders = (app, request, reply) => {
32
+ const modifyHeaders = app.webiny.plugins.byType(ModifyResponseHeadersPlugin.type);
33
+ const replyHeaders = reply.getHeaders();
34
+ const headers = ResponseHeaders.create(replyHeaders);
35
+ modifyHeaders.forEach(plugin => {
36
+ plugin.modify(request, headers);
47
37
  });
38
+
39
+ // Exclude 'set-cookie' header to avoid duplication.
40
+ // Cookies are managed by @fastify/cookie and calling reply.headers() with 'set-cookie' duplicates them.
41
+ const headersToSet = headers.getHeaders();
42
+ delete headersToSet["set-cookie"];
43
+ reply.headers(headersToSet);
48
44
  };
49
- const OPTIONS_HEADERS = {
50
- "Access-Control-Max-Age": "86400",
51
- "Cache-Control": "public, max-age=86400"
52
- };
53
- const createHandler = params => {
45
+ export const createHandler = params => {
54
46
  const definedRoutes = {
55
47
  POST: [],
56
48
  GET: [],
@@ -67,33 +59,39 @@ const createHandler = params => {
67
59
  PROPPATCH: [],
68
60
  SEARCH: [],
69
61
  TRACE: [],
70
- UNLOCK: []
62
+ UNLOCK: [],
63
+ REPORT: [],
64
+ MKCALENDAR: []
71
65
  };
72
66
  const throwOnDefinedRoute = (type, path, options) => {
73
67
  if (type === "ALL") {
74
- const all = Object.keys(definedRoutes).some(key => {
68
+ const all = Object.keys(definedRoutes).find(k => {
69
+ const key = k.toUpperCase();
75
70
  const routes = definedRoutes[key];
76
71
  return routes.includes(path);
77
72
  });
78
73
  if (!all) {
79
74
  return;
80
75
  }
81
- throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
76
+ console.error(`Error while registering onAll route. One of the routes is already defined.`);
77
+ console.error(JSON.stringify(all));
78
+ throw new WebinyError(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
82
79
  type,
83
80
  path
84
81
  });
85
82
  } else if (definedRoutes[type].includes(path) === false) {
86
83
  return;
87
- } else if ((options === null || options === void 0 ? void 0 : options.override) === true) {
84
+ } else if (options?.override === true) {
88
85
  return;
89
86
  }
90
- throw new _error.default(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
87
+ console.error(`Error while trying to override route: [${type}] ${path}`);
88
+ throw new WebinyError(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
91
89
  type,
92
90
  path
93
91
  });
94
92
  };
95
- const addDefinedRoute = (inputType, path) => {
96
- const type = inputType.toUpperCase();
93
+ const addDefinedRoute = (input, path) => {
94
+ const type = input.toUpperCase();
97
95
  if (!definedRoutes[type]) {
98
96
  return;
99
97
  } else if (definedRoutes[type].includes(path)) {
@@ -101,12 +99,20 @@ const createHandler = params => {
101
99
  }
102
100
  definedRoutes[type].push(path);
103
101
  };
102
+
104
103
  /**
105
104
  * We must attach the server to our internal context if we want to have it accessible.
106
105
  */
107
- const app = (0, _fastify.default)((0, _objectSpread2.default)({}, params.options || {}));
106
+ const app = fastify({
107
+ bodyLimit: 536870912,
108
+ // 512MB
109
+ disableRequestLogging: true,
110
+ allowErrorHandlerOverride: true,
111
+ ...(params.options || {})
112
+ });
113
+
108
114
  /**
109
- * We need to register routes in our system so we can output headers later on and dissallow overriding routes.
115
+ * We need to register routes in our system to output headers later on, and disallow route overriding.
110
116
  */
111
117
  app.addHook("onRoute", route => {
112
118
  const method = route.method;
@@ -119,11 +125,31 @@ const createHandler = params => {
119
125
  addDefinedRoute(method, route.path);
120
126
  });
121
127
  /**
128
+ * ############################
129
+ * Register the Fastify plugins.
130
+ */
131
+ /**
132
+ * Package @fastify/cookie
122
133
  *
134
+ * https://github.com/fastify/fastify-cookie
123
135
  */
124
- app.register(_cookie.default, {
136
+ app.register(fastifyCookie, {
125
137
  parseOptions: {} // options for parsing cookies
126
138
  });
139
+ /**
140
+ * Package @fastify/compress
141
+ *
142
+ * https://github.com/fastify/fastify-compress
143
+ */
144
+ app.register(fastifyCompress, {
145
+ global: true,
146
+ threshold: 1024,
147
+ onUnsupportedEncoding: (encoding, _, reply) => {
148
+ reply.code(406);
149
+ return `We do not support the ${encoding} encoding.`;
150
+ },
151
+ inflateIfDeflated: true
152
+ });
127
153
  /**
128
154
  * Route helpers - mostly for users.
129
155
  */
@@ -162,106 +188,256 @@ const createHandler = params => {
162
188
  app.head(path, handler);
163
189
  }
164
190
  };
165
- const context = new _Context.Context({
166
- plugins: [
167
- /**
168
- * We must have handlerClient by default.
169
- * And it must be one of the first context plugins applied.
170
- */
171
- (0, _handlerClient.createHandlerClient)(), ...(params.plugins || [])],
172
- /**
173
- * Inserted via webpack on build time.
174
- */
175
- WEBINY_VERSION: process.env.WEBINY_VERSION,
176
- server: app,
177
- routes
178
- });
179
- /**
180
- * We are attaching our custom context to webiny variable on the fastify app so it is accessible everywhere
181
- */
182
- app.decorate("webiny", context);
183
-
191
+ let context;
192
+ const plugins = new PluginsContainer([
184
193
  /**
185
- * We have few types of triggers:
186
- * * Events - EventPlugin
187
- * * Routes - RoutePlugin
188
- *
189
- * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
194
+ * We must have handlerClient by default.
195
+ * And it must be one of the first context plugins applied.
190
196
  */
191
- const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
197
+ createHandlerClient()]);
198
+ plugins.merge(params.plugins || []);
199
+ try {
200
+ context = new Context({
201
+ plugins,
202
+ /**
203
+ * Inserted via webpack at build time.
204
+ */
205
+ WEBINY_VERSION: process.env.WEBINY_VERSION,
206
+ routes
207
+ });
208
+ } catch (ex) {
209
+ console.error(`Error while constructing the Context.`);
210
+ console.error(stringifyError(ex));
211
+ throw ex;
212
+ }
192
213
 
193
214
  /**
194
- * Add routes to the system.
215
+ * We are attaching our custom context to webiny variable on the fastify app, so it is accessible everywhere.
195
216
  */
196
- for (const plugin of routePlugins) {
197
- plugin.cb((0, _objectSpread2.default)((0, _objectSpread2.default)({}, app.webiny.routes), {}, {
198
- context: app.webiny
199
- }));
200
- }
217
+ app.decorate("webiny", context);
201
218
 
202
219
  /**
203
- * On every request we add default headers, which can be changed later.
204
- * Also, if it is an options request, we skip everything after this hook and output options headers.
220
+ * To prevent Unsupported Media Type errors on OPTIONS requests with a body,
221
+ * we need to have a custom parser
205
222
  */
206
- app.addHook("onRequest", async (request, reply) => {
207
- const defaultHeaders = getDefaultHeaders(definedRoutes);
208
- reply.headers(defaultHeaders);
209
- if (request.method !== "OPTIONS") {
223
+ app.addContentTypeParser("application/json", {
224
+ parseAs: "string",
225
+ bodyLimit: 1024 * 1024
226
+ }, (req, body, done) => {
227
+ if (req.method === "OPTIONS") {
228
+ done(null, undefined);
210
229
  return;
211
230
  }
212
- const raw = reply.code(204).hijack().raw;
213
- const headers = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, defaultHeaders), OPTIONS_HEADERS);
214
- for (const key in headers) {
215
- raw.setHeader(key, headers[key]);
216
- }
217
- raw.end("");
218
- });
219
- app.addHook("preParsing", async request => {
220
- app.webiny.request = request;
221
- const plugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
222
- for (const plugin of plugins) {
223
- await plugin.apply(app.webiny);
231
+ try {
232
+ const json = typeof body === "string" ? body : body.toString("utf8");
233
+ done(null, JSON.parse(json));
234
+ } catch (err) {
235
+ done(err);
224
236
  }
225
237
  });
238
+
226
239
  /**
240
+ * With this we ensure that an undefined request body is not parsed on OPTIONS requests,
241
+ * in case there's a `content-type` header set for whatever reason.
227
242
  *
243
+ * @see https://fastify.dev/docs/latest/Reference/ContentTypeParser/#content-type-parser
228
244
  */
229
- app.addHook("preHandler", async () => {
230
- const plugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
231
- for (const plugin of plugins) {
232
- await plugin.apply(app.webiny);
245
+ app.addHook("onRequest", async request => {
246
+ if (request.method === "OPTIONS" && request.body === undefined) {
247
+ request.headers["content-type"] = undefined;
233
248
  }
234
249
  });
235
250
 
236
251
  /**
237
- *
252
+ * At this point, request body is properly parsed, and we can execute Webiny business logic.
253
+ * - set default headers
254
+ * - process `HandlerOnRequestPlugin`
255
+ * - if OPTIONS request, exit early
256
+ * - process `ContextPlugin`
257
+ * - process `BeforeHandlerPlugin`
238
258
  */
239
- const preSerialization = async (_, __, payload) => {
240
- const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
241
- for (const plugin of plugins) {
242
- await plugin.handle(app.webiny, payload);
259
+ app.addHook("preHandler", async (request, reply) => {
260
+ app.webiny.request = request;
261
+ app.webiny.reply = reply;
262
+
263
+ // Bind request and reply to DI container for runtime access
264
+ if (app.webiny.container) {
265
+ app.webiny.container.registerInstance(Request, request);
266
+ app.webiny.container.registerInstance(Reply, reply);
267
+ }
268
+ /**
269
+ * Default code to 200 - so we do not need to set it again.
270
+ * Usually we set errors manually when we use reply.send.
271
+ */
272
+ reply.code(200);
273
+ const handlerOnRequestPlugins = app.webiny.plugins.byType(HandlerOnRequestPlugin.type);
274
+ const contextPlugins = app.webiny.plugins.byType(ContextPlugin.type);
275
+ const beforeHandlerPlugins = app.webiny.plugins.byType(BeforeHandlerPlugin.type);
276
+ const modifyHeadersPlugins = app.webiny.plugins.byType(ModifyResponseHeadersPlugin.type);
277
+ const preHandler = new PreHandler([new SetDefaultHeaders(definedRoutes), new ProcessHandlerOnRequestPlugins(handlerOnRequestPlugins), new IfNotOptionsRequest([new ProcessContextPlugins(app.webiny, contextPlugins), new ProcessBeforeHandlerPlugins(app.webiny, beforeHandlerPlugins)]), new IfOptionsRequest([new SendEarlyOptionsResponse(modifyHeadersPlugins)])]);
278
+ await preHandler.execute(request, reply, app.webiny);
279
+ });
280
+ app.addHook("preSerialization", async (_, __, payload) => {
281
+ const plugins = app.webiny.plugins.byType(HandlerResultPlugin.type);
282
+ let name;
283
+ try {
284
+ for (const plugin of plugins) {
285
+ name = plugin.name;
286
+ await plugin.handle(app.webiny, payload);
287
+ }
288
+ } catch (ex) {
289
+ console.error(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
290
+ console.error(stringifyError(ex));
291
+ throw ex;
243
292
  }
244
293
  return payload;
245
- };
246
- app.addHook("preSerialization", preSerialization);
294
+ });
295
+ app.setErrorHandler(async (error, _, reply) => {
296
+ /**
297
+ * IMPORTANT! Do not send anything if reply was already sent.
298
+ */
299
+ if (reply.sent) {
300
+ console.warn("Reply already sent, cannot send the result (handler:setErrorHandler).");
301
+ return reply;
302
+ }
303
+ if (error.code?.startsWith("Authentication/")) {
304
+ return reply.status(401).headers({
305
+ "Cache-Control": "no-store"
306
+ }).send(JSON.stringify({
307
+ message: error.message,
308
+ code: error.code
309
+ }));
310
+ }
311
+ if (error.code === "Tenancy/TenantDisabled") {
312
+ return reply.status(503).headers({
313
+ "Cache-Control": "no-store"
314
+ }).send(JSON.stringify({
315
+ message: error.message,
316
+ code: error.code
317
+ }));
318
+ }
319
+ return reply.status(500).headers({
320
+ "Cache-Control": "no-store"
321
+ }).send(
322
+ /**
323
+ * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
324
+ */
325
+ JSON.stringify({
326
+ message: error.message,
327
+ code: error.code,
328
+ data: error.data
329
+ }));
330
+ });
247
331
  app.addHook("onError", async (_, reply, error) => {
248
- const plugins = app.webiny.plugins.byType(_HandlerErrorPlugin.HandlerErrorPlugin.type);
249
- // Log error to cloud, as these can be extremely annoying to debug!
250
- console.log("@webiny/handler");
251
- console.log(JSON.stringify((0, _objectSpread2.default)((0, _objectSpread2.default)({}, error || {}), {}, {
252
- message: error === null || error === void 0 ? void 0 : error.message,
253
- code: error === null || error === void 0 ? void 0 : error.code
254
- })));
255
- const handler = (0, _middleware.middleware)(plugins.map(pl => {
332
+ const plugins = app.webiny.plugins.byType(HandlerErrorPlugin.type);
333
+ /**
334
+ * Log error to cloud, as these can be extremely annoying to debug!
335
+ */
336
+ console.error("Logging error in @webiny/handler");
337
+ try {
338
+ console.error(stringifyError(error));
339
+ } catch (ex) {
340
+ console.warn("Could not stringify error:");
341
+ console.log(error);
342
+ console.error("Stringify error:", ex);
343
+ }
344
+ /**
345
+ * IMPORTANT! Do not send anything if reply was already sent.
346
+ */
347
+ if (!reply.sent) {
348
+ reply.status(500).headers({
349
+ "Cache-Control": "no-store"
350
+ }).send(
351
+ /**
352
+ * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
353
+ */
354
+ JSON.stringify({
355
+ message: error.message,
356
+ code: error.code,
357
+ data: error.data
358
+ }));
359
+ } else {
360
+ console.warn("Reply already sent, cannot send the result (handler:addHook:onError).");
361
+ }
362
+ const handler = middleware(plugins.map(pl => {
256
363
  return (context, error, next) => {
257
364
  return pl.handle(context, error, next);
258
365
  };
259
366
  }));
260
367
  await handler(app.webiny, error);
261
- return reply.headers({
262
- "Cache-Control": "no-store"
263
- }).status(500);
368
+ return reply;
264
369
  });
370
+
371
+ /**
372
+ * Apply response headers modifier plugins.
373
+ */
374
+ app.addHook("onSend", async (request, reply, input) => {
375
+ modifyResponseHeaders(app, request, reply);
376
+ const plugins = app.webiny.plugins.byType(OnRequestResponseSendPlugin.type);
377
+ let payload = input;
378
+ for (const plugin of plugins) {
379
+ payload = await plugin.exec(request, reply, payload);
380
+ }
381
+ return payload;
382
+ });
383
+
384
+ /**
385
+ * We need to output the benchmark results at the end of the request in both response and timeout cases
386
+ */
387
+ app.addHook("onResponse", async () => {
388
+ await context.benchmark.output();
389
+ });
390
+ app.addHook("onTimeout", async (request, reply) => {
391
+ const plugins = app.webiny.plugins.byType(OnRequestTimeoutPlugin.type);
392
+ for (const plugin of plugins) {
393
+ await plugin.exec(request, reply);
394
+ }
395
+ await context.benchmark.output();
396
+ });
397
+
398
+ /**
399
+ * With these plugins we give users possibility to do anything they want on our fastify instance.
400
+ */
401
+ const modifyPlugins = app.webiny.plugins.byType(ModifyFastifyPlugin.type);
402
+ let modifyFastifyPluginName;
403
+ try {
404
+ for (const plugin of modifyPlugins) {
405
+ modifyFastifyPluginName = plugin.name;
406
+ plugin.modify(app);
407
+ }
408
+ } catch (ex) {
409
+ console.error(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
410
+ console.error(stringifyError(ex));
411
+ throw ex;
412
+ }
413
+
414
+ /**
415
+ * We have few types of triggers:
416
+ * * Events - EventPlugin
417
+ * * Routes - RoutePlugin
418
+ *
419
+ * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
420
+ */
421
+ const routePlugins = app.webiny.plugins.byType(RoutePlugin.type);
422
+
423
+ /**
424
+ * Add routes to the system.
425
+ */
426
+ let routePluginName;
427
+ try {
428
+ for (const plugin of routePlugins) {
429
+ routePluginName = plugin.name;
430
+ plugin.cb({
431
+ ...app.webiny.routes,
432
+ context: app.webiny
433
+ });
434
+ }
435
+ } catch (ex) {
436
+ console.error(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
437
+ console.error(stringifyError(ex));
438
+ throw ex;
439
+ }
265
440
  return app;
266
441
  };
267
- exports.createHandler = createHandler;
442
+
443
+ //# sourceMappingURL=fastify.js.map