@webiny/handler 0.0.0-unstable.d7f521b032 → 0.0.0-unstable.de38392959

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/fastify.js CHANGED
@@ -1,79 +1,66 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports.createHandler = void 0;
9
-
10
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
11
-
8
+ var _types = require("@webiny/plugins/types");
12
9
  var _fastify = _interopRequireDefault(require("fastify"));
13
-
14
10
  var _utils = require("@webiny/utils");
15
-
16
11
  var _Context = require("./Context");
17
-
18
12
  var _error = _interopRequireDefault(require("@webiny/error"));
19
-
20
13
  var _RoutePlugin = require("./plugins/RoutePlugin");
21
-
22
14
  var _handlerClient = require("@webiny/handler-client");
23
-
24
15
  var _cookie = _interopRequireDefault(require("@fastify/cookie"));
25
-
26
16
  var _compress = _interopRequireDefault(require("@fastify/compress"));
27
-
28
17
  var _middleware = require("./middleware");
29
-
30
18
  var _api = require("@webiny/api");
31
-
32
19
  var _BeforeHandlerPlugin = require("./plugins/BeforeHandlerPlugin");
33
-
34
20
  var _HandlerResultPlugin = require("./plugins/HandlerResultPlugin");
35
-
36
21
  var _HandlerErrorPlugin = require("./plugins/HandlerErrorPlugin");
37
-
38
22
  var _ModifyFastifyPlugin = require("./plugins/ModifyFastifyPlugin");
39
-
40
23
  var _HandlerOnRequestPlugin = require("./plugins/HandlerOnRequestPlugin");
41
-
42
- const DEFAULT_HEADERS = (0, _objectSpread2.default)({
43
- "Cache-Control": "no-store",
44
- "Content-Type": "application/json; charset=utf-8",
45
- "Access-Control-Allow-Origin": "*",
46
- "Access-Control-Allow-Headers": "*",
47
- "Access-Control-Allow-Methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH"
48
- }, (0, _utils.getWebinyVersionHeaders)());
49
-
24
+ var _ResponseHeaders = require("./ResponseHeaders");
25
+ var _ModifyResponseHeadersPlugin = require("./plugins/ModifyResponseHeadersPlugin");
26
+ function createDefaultHeaders() {
27
+ return _ResponseHeaders.ResponseHeaders.create({
28
+ "content-type": "application/json; charset=utf-8",
29
+ "cache-control": "no-store",
30
+ "access-control-allow-origin": "*",
31
+ "access-control-allow-headers": "*",
32
+ "access-control-allow-methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH",
33
+ ...(0, _utils.getWebinyVersionHeaders)()
34
+ });
35
+ }
36
+ const getDefaultOptionsHeaders = () => {
37
+ return _ResponseHeaders.ResponseHeaders.create({
38
+ "access-control-max-age": "86400",
39
+ "cache-control": "public, max-age=86400"
40
+ });
41
+ };
50
42
  const getDefaultHeaders = routes => {
43
+ const headers = createDefaultHeaders();
44
+
51
45
  /**
52
46
  * If we are accepting all headers, just output that one.
53
47
  */
54
48
  const keys = Object.keys(routes);
55
49
  const all = keys.every(key => routes[key].length > 0);
56
-
57
50
  if (all) {
58
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
59
- "Access-Control-Allow-Methods": "*"
60
- });
61
- }
62
-
63
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
64
- "Access-Control-Allow-Methods": keys.filter(type => {
65
- if (!routes[type] || Array.isArray(routes[type]) === false) {
51
+ headers.set("access-control-allow-methods", "*");
52
+ } else {
53
+ const allowedMethods = keys.filter(type => {
54
+ if (!routes[type] || !Array.isArray(routes[type])) {
66
55
  return false;
67
56
  }
68
-
69
57
  return routes[type].length > 0;
70
- }).sort().join(",")
71
- });
58
+ }).sort().join(",");
59
+ headers.set("access-control-allow-methods", allowedMethods);
60
+ }
61
+ return headers;
72
62
  };
73
-
74
63
  const stringifyError = error => {
75
- var _error$constructor;
76
-
77
64
  const {
78
65
  name,
79
66
  message,
@@ -81,21 +68,16 @@ const stringifyError = error => {
81
68
  stack,
82
69
  data
83
70
  } = error;
84
- return JSON.stringify((0, _objectSpread2.default)((0, _objectSpread2.default)({}, error), {}, {
85
- constructorName: ((_error$constructor = error.constructor) === null || _error$constructor === void 0 ? void 0 : _error$constructor.name) || "UnknownError",
71
+ return JSON.stringify({
72
+ ...error,
73
+ constructorName: error.constructor?.name || "UnknownError",
86
74
  name: name || "No error name",
87
75
  message: message || "No error message",
88
76
  code: code || "NO_CODE",
89
77
  data,
90
78
  stack: process.env.DEBUG === "true" ? stack : "Turn on the debug flag to see the stack."
91
- }));
92
- };
93
-
94
- const OPTIONS_HEADERS = {
95
- "Access-Control-Max-Age": "86400",
96
- "Cache-Control": "public, max-age=86400"
79
+ });
97
80
  };
98
-
99
81
  const createHandler = params => {
100
82
  const definedRoutes = {
101
83
  POST: [],
@@ -115,90 +97,78 @@ const createHandler = params => {
115
97
  TRACE: [],
116
98
  UNLOCK: []
117
99
  };
118
-
119
100
  const throwOnDefinedRoute = (type, path, options) => {
120
101
  if (type === "ALL") {
121
102
  const all = Object.keys(definedRoutes).find(key => {
122
103
  const routes = definedRoutes[key];
123
104
  return routes.includes(path);
124
105
  });
125
-
126
106
  if (!all) {
127
107
  return;
128
108
  }
129
-
130
- console.log(`Error while registering onAll route. One of the routes is already defined.`);
131
- console.log(JSON.stringify(all));
109
+ console.error(`Error while registering onAll route. One of the routes is already defined.`);
110
+ console.error(JSON.stringify(all));
132
111
  throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
133
112
  type,
134
113
  path
135
114
  });
136
115
  } else if (definedRoutes[type].includes(path) === false) {
137
116
  return;
138
- } else if ((options === null || options === void 0 ? void 0 : options.override) === true) {
117
+ } else if (options?.override === true) {
139
118
  return;
140
119
  }
141
-
142
- console.log(`Error while trying to override route: [${type}] ${path}`);
120
+ console.error(`Error while trying to override route: [${type}] ${path}`);
143
121
  throw new _error.default(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
144
122
  type,
145
123
  path
146
124
  });
147
125
  };
148
-
149
126
  const addDefinedRoute = (type, path) => {
150
127
  if (!definedRoutes[type]) {
151
128
  return;
152
129
  } else if (definedRoutes[type].includes(path)) {
153
130
  return;
154
131
  }
155
-
156
132
  definedRoutes[type].push(path);
157
133
  };
158
134
  /**
159
135
  * We must attach the server to our internal context if we want to have it accessible.
160
136
  */
161
-
162
-
163
- const app = (0, _fastify.default)((0, _objectSpread2.default)({}, params.options || {}));
137
+ const app = (0, _fastify.default)({
138
+ bodyLimit: 10485760,
139
+ // 10MB
140
+ ...(params.options || {})
141
+ });
164
142
  /**
165
143
  * We need to register routes in our system so we can output headers later on and dissallow overriding routes.
166
144
  */
167
-
168
145
  app.addHook("onRoute", route => {
169
146
  const method = route.method;
170
-
171
147
  if (Array.isArray(method)) {
172
148
  for (const m of method) {
173
149
  addDefinedRoute(m, route.path);
174
150
  }
175
-
176
151
  return;
177
152
  }
178
-
179
153
  addDefinedRoute(method, route.path);
180
154
  });
181
155
  /**
182
156
  * ############################
183
157
  * Register the Fastify plugins.
184
158
  */
185
-
186
159
  /**
187
160
  * Package @fastify/cookie
188
161
  *
189
162
  * https://github.com/fastify/fastify-cookie
190
163
  */
191
-
192
164
  app.register(_cookie.default, {
193
165
  parseOptions: {} // options for parsing cookies
194
-
195
166
  });
196
167
  /**
197
168
  * Package @fastify/compress
198
169
  *
199
170
  * https://github.com/fastify/fastify-compress
200
171
  */
201
-
202
172
  app.register(_compress.default, {
203
173
  global: true,
204
174
  threshold: 1024,
@@ -211,7 +181,6 @@ const createHandler = params => {
211
181
  /**
212
182
  * Route helpers - mostly for users.
213
183
  */
214
-
215
184
  const routes = {
216
185
  defined: definedRoutes,
217
186
  onPost: (path, handler, options) => {
@@ -248,92 +217,61 @@ const createHandler = params => {
248
217
  }
249
218
  };
250
219
  let context;
251
-
220
+ const plugins = new _types.PluginsContainer([
221
+ /**
222
+ * We must have handlerClient by default.
223
+ * And it must be one of the first context plugins applied.
224
+ */
225
+ (0, _handlerClient.createHandlerClient)()]);
226
+ plugins.merge(params.plugins || []);
252
227
  try {
253
228
  context = new _Context.Context({
254
- plugins: [
229
+ plugins,
255
230
  /**
256
- * We must have handlerClient by default.
257
- * And it must be one of the first context plugins applied.
258
- */
259
- (0, _handlerClient.createHandlerClient)(), ...(params.plugins || [])],
260
-
261
- /**
262
- * Inserted via webpack on build time.
231
+ * Inserted via webpack at build time.
263
232
  */
264
233
  WEBINY_VERSION: process.env.WEBINY_VERSION,
265
- server: app,
266
234
  routes
267
235
  });
268
236
  } catch (ex) {
269
- console.log(`Error while constructing the Context.`);
270
- console.log(stringifyError(ex));
237
+ console.error(`Error while constructing the Context.`);
238
+ console.error(stringifyError(ex));
271
239
  throw ex;
272
240
  }
241
+
273
242
  /**
274
243
  * We are attaching our custom context to webiny variable on the fastify app, so it is accessible everywhere.
275
244
  */
276
-
277
-
278
245
  app.decorate("webiny", context);
279
- /**
280
- * We have few types of triggers:
281
- * * Events - EventPlugin
282
- * * Routes - RoutePlugin
283
- *
284
- * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
285
- */
286
246
 
287
- const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
288
- /**
289
- * Add routes to the system.
290
- */
291
-
292
- let routePluginName;
293
-
294
- try {
295
- for (const plugin of routePlugins) {
296
- routePluginName = plugin.name;
297
- plugin.cb((0, _objectSpread2.default)((0, _objectSpread2.default)({}, app.webiny.routes), {}, {
298
- context: app.webiny
299
- }));
300
- }
301
- } catch (ex) {
302
- console.log(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
303
- console.log(stringifyError(ex));
304
- throw ex;
305
- }
306
247
  /**
307
248
  * On every request we add default headers, which can be changed later.
308
249
  * Also, if it is an options request, we skip everything after this hook and output options headers.
309
250
  */
310
-
311
-
312
251
  app.addHook("onRequest", async (request, reply) => {
252
+ const isOptionsRequest = request.method === "OPTIONS";
313
253
  /**
314
254
  * Our default headers are always set. Users can override them.
315
255
  */
316
256
  const defaultHeaders = getDefaultHeaders(definedRoutes);
317
- reply.headers(defaultHeaders);
257
+ const initialHeaders = isOptionsRequest ? defaultHeaders.merge(getDefaultOptionsHeaders()) : defaultHeaders;
258
+ reply.headers(initialHeaders.getHeaders());
318
259
  /**
319
260
  * Users can define their own custom handlers for the onRequest event - so let's run them first.
320
261
  */
321
-
322
262
  const plugins = app.webiny.plugins.byType(_HandlerOnRequestPlugin.HandlerOnRequestPlugin.type);
323
263
  let name;
324
-
325
264
  try {
326
265
  for (const plugin of plugins) {
327
266
  name = plugin.name;
328
267
  const result = await plugin.exec(request, reply);
329
-
330
268
  if (result === false) {
331
269
  return;
332
270
  }
333
271
  }
334
272
  } catch (ex) {
335
- console.log(`Error while running the "HandlerOnRequestPlugin" ${name ? `(${name})` : ""} plugin in the onRequest hook.`);
336
- console.log(stringifyError(ex));
273
+ console.error(`Error while running the "HandlerOnRequestPlugin" ${name ? `(${name})` : ""} plugin in the onRequest hook.`);
274
+ console.error(stringifyError(ex));
337
275
  throw ex;
338
276
  }
339
277
  /**
@@ -341,83 +279,73 @@ const createHandler = params => {
341
279
  *
342
280
  * Users can prevent this by creating their own HandlerOnRequestPlugin and returning false as the result of the callable.
343
281
  */
344
-
345
-
346
- if (request.method !== "OPTIONS") {
282
+ if (!isOptionsRequest) {
347
283
  return;
348
284
  }
349
-
350
285
  if (reply.sent) {
351
286
  /**
352
287
  * At this point throwing an exception will not do anything with the response. So just log it.
353
288
  */
354
- console.log(JSON.stringify({
289
+ console.error(JSON.stringify({
355
290
  message: `Output was already sent. Please check custom plugins of type "HandlerOnRequestPlugin".`,
356
291
  explanation: "This error can happen if the user plugin ended the reply, but did not return false as response."
357
292
  }));
358
293
  return;
359
294
  }
360
-
361
- reply.headers((0, _objectSpread2.default)((0, _objectSpread2.default)({}, defaultHeaders), OPTIONS_HEADERS)).code(204).send("").hijack();
295
+ reply.code(204).send("").hijack();
362
296
  });
363
297
  app.addHook("preParsing", async (request, reply) => {
364
298
  app.webiny.request = request;
365
299
  app.webiny.reply = reply;
366
300
  const plugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
367
301
  let name;
368
-
369
302
  try {
370
303
  for (const plugin of plugins) {
371
304
  name = plugin.name;
372
305
  await plugin.apply(app.webiny);
373
306
  }
374
307
  } catch (ex) {
375
- console.log(`Error while running the "ContextPlugin" ${name ? `(${name})` : ""} plugin in the preParsing hook.`);
376
- console.log(stringifyError(ex));
308
+ console.error(`Error while running the "ContextPlugin" ${name ? `(${name})` : ""} plugin in the preParsing hook.`);
309
+ console.error(stringifyError(ex));
377
310
  throw ex;
378
311
  }
379
312
  });
380
313
  /**
381
314
  *
382
315
  */
383
-
384
316
  app.addHook("preHandler", async () => {
385
317
  const plugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
386
318
  let name;
387
-
388
319
  try {
389
320
  for (const plugin of plugins) {
390
321
  name = plugin.name;
391
322
  await plugin.apply(app.webiny);
392
323
  }
393
324
  } catch (ex) {
394
- console.log(`Error while running the "BeforeHandlerPlugin" ${name ? `(${name})` : ""} plugin in the preHandler hook.`);
395
- console.log(stringifyError(ex));
325
+ console.error(`Error while running the "BeforeHandlerPlugin" ${name ? `(${name})` : ""} plugin in the preHandler hook.`);
326
+ console.error(stringifyError(ex));
396
327
  throw ex;
397
328
  }
398
329
  });
330
+
399
331
  /**
400
332
  *
401
333
  */
402
-
403
334
  const preSerialization = async (_, __, payload) => {
404
335
  const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
405
336
  let name;
406
-
407
337
  try {
408
338
  for (const plugin of plugins) {
409
339
  name = plugin.name;
410
340
  await plugin.handle(app.webiny, payload);
411
341
  }
412
342
  } catch (ex) {
413
- console.log(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
414
- console.log(stringifyError(ex));
343
+ console.error(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
344
+ console.error(stringifyError(ex));
415
345
  throw ex;
416
346
  }
417
-
418
347
  return payload;
419
348
  };
420
-
421
349
  app.addHook("preSerialization", preSerialization);
422
350
  app.setErrorHandler(async (error, request, reply) => {
423
351
  return reply.status(500).headers({
@@ -437,9 +365,8 @@ const createHandler = params => {
437
365
  /**
438
366
  * Log error to cloud, as these can be extremely annoying to debug!
439
367
  */
440
-
441
- console.log("@webiny/handler");
442
- console.log(stringifyError(error));
368
+ console.error("@webiny/handler");
369
+ console.error(stringifyError(error));
443
370
  reply.status(500).headers({
444
371
  "Cache-Control": "no-store"
445
372
  }).send(
@@ -459,25 +386,74 @@ const createHandler = params => {
459
386
  await handler(app.webiny, error);
460
387
  return reply;
461
388
  });
389
+
390
+ /**
391
+ * Apply response headers modifier plugins.
392
+ */
393
+ app.addHook("onSend", async (request, reply, payload) => {
394
+ const modifyHeaders = app.webiny.plugins.byType(_ModifyResponseHeadersPlugin.ModifyResponseHeadersPlugin.type);
395
+ const headers = _ResponseHeaders.ResponseHeaders.create(reply.getHeaders());
396
+ modifyHeaders.forEach(plugin => {
397
+ plugin.modify(request, headers);
398
+ });
399
+ reply.headers(headers.getHeaders());
400
+ return payload;
401
+ });
402
+
462
403
  /**
463
- * With these plugins we give users possibility to do anything they want on our fastify instance.
404
+ * We need to output the benchmark results at the end of the request in both response and timeout cases
464
405
  */
406
+ app.addHook("onResponse", async () => {
407
+ await context.benchmark.output();
408
+ });
409
+ app.addHook("onTimeout", async () => {
410
+ await context.benchmark.output();
411
+ });
465
412
 
413
+ /**
414
+ * With these plugins we give users possibility to do anything they want on our fastify instance.
415
+ */
466
416
  const modifyPlugins = app.webiny.plugins.byType(_ModifyFastifyPlugin.ModifyFastifyPlugin.type);
467
417
  let modifyFastifyPluginName;
468
-
469
418
  try {
470
419
  for (const plugin of modifyPlugins) {
471
420
  modifyFastifyPluginName = plugin.name;
472
421
  plugin.modify(app);
473
422
  }
474
423
  } catch (ex) {
475
- console.log(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
476
- console.log(stringifyError(ex));
424
+ console.error(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
425
+ console.error(stringifyError(ex));
477
426
  throw ex;
478
427
  }
479
428
 
429
+ /**
430
+ * We have few types of triggers:
431
+ * * Events - EventPlugin
432
+ * * Routes - RoutePlugin
433
+ *
434
+ * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
435
+ */
436
+ const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
437
+
438
+ /**
439
+ * Add routes to the system.
440
+ */
441
+ let routePluginName;
442
+ try {
443
+ for (const plugin of routePlugins) {
444
+ routePluginName = plugin.name;
445
+ plugin.cb({
446
+ ...app.webiny.routes,
447
+ context: app.webiny
448
+ });
449
+ }
450
+ } catch (ex) {
451
+ console.error(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
452
+ console.error(stringifyError(ex));
453
+ throw ex;
454
+ }
480
455
  return app;
481
456
  };
457
+ exports.createHandler = createHandler;
482
458
 
483
- exports.createHandler = createHandler;
459
+ //# sourceMappingURL=fastify.js.map