@duplojs/http 0.7.4 → 0.8.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.
Files changed (151) hide show
  1. package/dist/client/getBody.cjs +3 -3
  2. package/dist/client/getBody.mjs +3 -3
  3. package/dist/client/hooks.cjs +45 -0
  4. package/dist/client/hooks.d.ts +6 -1
  5. package/dist/client/hooks.mjs +41 -1
  6. package/dist/client/httpClient.cjs +25 -1
  7. package/dist/client/httpClient.d.ts +8 -3
  8. package/dist/client/httpClient.mjs +25 -1
  9. package/dist/client/index.cjs +7 -0
  10. package/dist/client/index.d.ts +1 -0
  11. package/dist/client/index.mjs +2 -1
  12. package/dist/client/insertParamsInPath.cjs +1 -1
  13. package/dist/client/insertParamsInPath.mjs +1 -1
  14. package/dist/client/promiseRequest.cjs +83 -26
  15. package/dist/client/promiseRequest.d.ts +46 -29
  16. package/dist/client/promiseRequest.mjs +83 -26
  17. package/dist/client/queryToString.cjs +1 -1
  18. package/dist/client/queryToString.mjs +1 -1
  19. package/dist/client/serverSentEvents.cjs +231 -0
  20. package/dist/client/serverSentEvents.d.ts +2 -0
  21. package/dist/client/serverSentEvents.mjs +208 -0
  22. package/dist/client/types/clientRequestParams.d.ts +2 -0
  23. package/dist/client/types/clientResponse.d.ts +34 -3
  24. package/dist/client/types/hooks.d.ts +17 -7
  25. package/dist/client/types/promiseRequestParams.d.ts +1 -0
  26. package/dist/client/types/serverRoute.d.ts +2 -0
  27. package/dist/core/builders/route/handler.d.ts +5 -2
  28. package/dist/core/defaultHooks/index.cjs +8 -0
  29. package/dist/core/defaultHooks/index.d.ts +1 -1
  30. package/dist/core/defaultHooks/index.mjs +8 -0
  31. package/dist/core/functionsBuilders/route/default.cjs +9 -13
  32. package/dist/core/functionsBuilders/route/default.mjs +2 -6
  33. package/dist/core/functionsBuilders/steps/create.d.ts +2 -2
  34. package/dist/core/functionsBuilders/steps/defaults/cutStep.cjs +1 -1
  35. package/dist/core/functionsBuilders/steps/defaults/cutStep.mjs +1 -1
  36. package/dist/core/functionsBuilders/steps/defaults/handlerStep.cjs +37 -17
  37. package/dist/core/functionsBuilders/steps/defaults/handlerStep.mjs +37 -17
  38. package/dist/core/functionsBuilders/steps/defaults/processStep.cjs +3 -3
  39. package/dist/core/functionsBuilders/steps/defaults/processStep.mjs +3 -3
  40. package/dist/core/hub/defaultEmptyReaderImplementation.cjs +9 -0
  41. package/dist/core/hub/defaultEmptyReaderImplementation.d.ts +1 -0
  42. package/dist/core/hub/defaultEmptyReaderImplementation.mjs +7 -0
  43. package/dist/core/hub/defaultMalformedUrlHandler.cjs +14 -0
  44. package/dist/core/hub/defaultMalformedUrlHandler.d.ts +10 -0
  45. package/dist/core/hub/defaultMalformedUrlHandler.mjs +12 -0
  46. package/dist/core/hub/defaultNotfoundHandler.d.ts +1 -1
  47. package/dist/core/hub/index.cjs +14 -1
  48. package/dist/core/hub/index.d.ts +4 -0
  49. package/dist/core/hub/index.mjs +13 -2
  50. package/dist/core/implementHttpServer.cjs +7 -2
  51. package/dist/core/implementHttpServer.d.ts +7 -1
  52. package/dist/core/implementHttpServer.mjs +5 -0
  53. package/dist/core/index.cjs +18 -0
  54. package/dist/core/index.d.ts +1 -0
  55. package/dist/core/index.mjs +8 -2
  56. package/dist/core/request/bodyController/base.cjs +24 -6
  57. package/dist/core/request/bodyController/base.d.ts +9 -0
  58. package/dist/core/request/bodyController/base.mjs +25 -8
  59. package/dist/core/request/bodyController/empty.cjs +11 -0
  60. package/dist/core/request/bodyController/empty.d.ts +3 -0
  61. package/dist/core/request/bodyController/empty.mjs +8 -0
  62. package/dist/core/request/bodyController/formData.d.ts +2 -2
  63. package/dist/core/request/bodyController/index.cjs +4 -0
  64. package/dist/core/request/bodyController/index.d.ts +1 -0
  65. package/dist/core/request/bodyController/index.mjs +2 -1
  66. package/dist/core/request/index.cjs +5 -0
  67. package/dist/core/request/index.d.ts +1 -1
  68. package/dist/core/request/index.mjs +6 -1
  69. package/dist/core/response/contract.cjs +17 -4
  70. package/dist/core/response/contract.d.ts +19 -4
  71. package/dist/core/response/contract.mjs +17 -4
  72. package/dist/core/response/index.cjs +2 -0
  73. package/dist/core/response/index.d.ts +1 -0
  74. package/dist/core/response/index.mjs +1 -0
  75. package/dist/core/response/serverSentEventsPredicted.cjs +23 -0
  76. package/dist/core/response/serverSentEventsPredicted.d.ts +14 -0
  77. package/dist/core/response/serverSentEventsPredicted.mjs +21 -0
  78. package/dist/core/route/hooks.cjs +9 -0
  79. package/dist/core/route/hooks.d.ts +10 -9
  80. package/dist/core/route/hooks.mjs +9 -1
  81. package/dist/core/route/index.cjs +1 -0
  82. package/dist/core/route/index.mjs +1 -1
  83. package/dist/core/router/buildSystemRoute.cjs +33 -0
  84. package/dist/core/router/buildSystemRoute.d.ts +11 -0
  85. package/dist/core/router/buildSystemRoute.mjs +31 -0
  86. package/dist/core/router/decodeUrl.cjs +5 -4
  87. package/dist/core/router/decodeUrl.d.ts +1 -1
  88. package/dist/core/router/decodeUrl.mjs +5 -4
  89. package/dist/core/router/index.cjs +24 -23
  90. package/dist/core/router/index.d.ts +1 -0
  91. package/dist/core/router/index.mjs +25 -25
  92. package/dist/core/serverSentEvents.cjs +96 -0
  93. package/dist/core/serverSentEvents.d.ts +33 -0
  94. package/dist/core/serverSentEvents.mjs +96 -0
  95. package/dist/core/steps/cut.d.ts +2 -2
  96. package/dist/core/steps/handler.d.ts +10 -5
  97. package/dist/interfaces/node/bodyReaders/formData/index.cjs +33 -14
  98. package/dist/interfaces/node/bodyReaders/formData/index.mjs +34 -15
  99. package/dist/interfaces/node/bodyReaders/formData/readRequestFormData.cjs +8 -11
  100. package/dist/interfaces/node/bodyReaders/formData/readRequestFormData.mjs +8 -11
  101. package/dist/interfaces/node/createHttpServer.cjs +2 -3
  102. package/dist/interfaces/node/createHttpServer.mjs +2 -3
  103. package/dist/interfaces/node/hooks/index.cjs +61 -38
  104. package/dist/interfaces/node/hooks/index.d.ts +6 -4
  105. package/dist/interfaces/node/hooks/index.mjs +61 -38
  106. package/dist/interfaces/node/index.cjs +1 -1
  107. package/dist/interfaces/node/index.mjs +1 -1
  108. package/dist/plugins/cacheController/createResponseHeader.cjs +43 -0
  109. package/dist/plugins/cacheController/createResponseHeader.d.ts +2 -0
  110. package/dist/plugins/cacheController/createResponseHeader.mjs +41 -0
  111. package/dist/plugins/cacheController/hooks.cjs +23 -0
  112. package/dist/plugins/cacheController/hooks.d.ts +4 -0
  113. package/dist/plugins/cacheController/hooks.mjs +21 -0
  114. package/dist/plugins/cacheController/index.cjs +10 -0
  115. package/dist/plugins/cacheController/index.d.ts +3 -0
  116. package/dist/plugins/cacheController/index.mjs +3 -0
  117. package/dist/plugins/cacheController/types/cacheControlDirectives.cjs +2 -0
  118. package/dist/plugins/cacheController/types/cacheControlDirectives.d.ts +16 -0
  119. package/dist/plugins/cacheController/types/cacheControlDirectives.mjs +1 -0
  120. package/dist/plugins/cacheController/types/index.cjs +4 -0
  121. package/dist/plugins/cacheController/types/index.d.ts +1 -0
  122. package/dist/plugins/cacheController/types/index.mjs +1 -0
  123. package/dist/plugins/codeGenerator/aggregateStepContract.cjs +9 -2
  124. package/dist/plugins/codeGenerator/aggregateStepContract.d.ts +1 -1
  125. package/dist/plugins/codeGenerator/aggregateStepContract.mjs +10 -3
  126. package/dist/plugins/codeGenerator/plugin.cjs +4 -4
  127. package/dist/plugins/codeGenerator/plugin.mjs +1 -1
  128. package/dist/plugins/openApiGenerator/aggregateStepContract.d.ts +2 -7
  129. package/dist/plugins/openApiGenerator/routeToOpenApi.cjs +46 -8
  130. package/dist/plugins/openApiGenerator/routeToOpenApi.d.ts +2 -2
  131. package/dist/plugins/openApiGenerator/routeToOpenApi.mjs +46 -8
  132. package/dist/plugins/openApiGenerator/types/endpointResponse.d.ts +7 -3
  133. package/dist/plugins/static/index.cjs +14 -0
  134. package/dist/plugins/static/index.d.ts +3 -0
  135. package/dist/plugins/static/index.mjs +3 -0
  136. package/dist/plugins/static/kind.cjs +9 -0
  137. package/dist/plugins/static/kind.d.ts +6 -0
  138. package/dist/plugins/static/kind.mjs +7 -0
  139. package/dist/plugins/static/makeRouteFile.cjs +62 -0
  140. package/dist/plugins/static/makeRouteFile.d.ts +48 -0
  141. package/dist/plugins/static/makeRouteFile.mjs +58 -0
  142. package/dist/plugins/static/makeRouteFolder.cjs +67 -0
  143. package/dist/plugins/static/makeRouteFolder.d.ts +39 -0
  144. package/dist/plugins/static/makeRouteFolder.mjs +65 -0
  145. package/dist/plugins/static/plugin.cjs +53 -0
  146. package/dist/plugins/static/plugin.d.ts +26 -0
  147. package/dist/plugins/static/plugin.mjs +50 -0
  148. package/package.json +18 -7
  149. /package/dist/plugins/codeGenerator/{typescriptTransfomer.cjs → typescriptTransformer.cjs} +0 -0
  150. /package/dist/plugins/codeGenerator/{typescriptTransfomer.d.ts → typescriptTransformer.d.ts} +0 -0
  151. /package/dist/plugins/codeGenerator/{typescriptTransfomer.mjs → typescriptTransformer.mjs} +0 -0
@@ -24,11 +24,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
24
24
  return utils.E.error(new error.BodyParseFormDataError("Wrong boundary."));
25
25
  }
26
26
  let valueAccumulator = firstValueAccumulator;
27
- const startPart = Buffer.from(`\r\n--${boundary}`);
28
- const endMultiPart = Buffer.from(`\r\n--${boundary}--`);
27
+ const startPart = Buffer.from(`\r\n--${boundary}\r\n`);
28
+ const endMultiPart = Buffer.from(`\r\n--${boundary}--\r\n`);
29
29
  let currentBuffer = bufferStart;
30
30
  let size = 0;
31
- const keep = endMultiPart.length - 1;
31
+ const keep = endMultiPart.length;
32
32
  let currentStream = undefined;
33
33
  let fileQuantity = 0;
34
34
  let currentFileSize = undefined;
@@ -114,11 +114,6 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
114
114
  return await treatError(new error.BodyParseFormDataError("Buffer size exceeds limit."));
115
115
  }
116
116
  while (true) {
117
- const endMultiPartIndex = currentBuffer.indexOf(endMultiPart);
118
- if (endMultiPartIndex !== -1) {
119
- // check if buffer contain end of transmissions
120
- currentBuffer = currentBuffer.subarray(0, endMultiPartIndex);
121
- }
122
117
  const startPartIndex = currentBuffer.indexOf(startPart);
123
118
  const endHeaderPartIndex = currentBuffer.indexOf(endHeaderPart);
124
119
  if (startPartIndex !== -1 && endHeaderPartIndex !== -1) {
@@ -156,9 +151,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
156
151
  }
157
152
  }
158
153
  }
159
- const resultChunk = await flushReceiveChunk(currentBuffer);
160
- if (resultChunk !== true) {
161
- return await treatError(resultChunk);
154
+ if (currentBuffer.indexOf(endMultiPart) === -1) {
155
+ const resultChunk = await flushReceiveChunk(currentBuffer.subarray(0, 2));
156
+ if (resultChunk !== true) {
157
+ return await treatError(resultChunk);
158
+ }
162
159
  }
163
160
  valueAccumulator = await currentStream?.onEndPart(valueAccumulator) ?? valueAccumulator;
164
161
  return valueAccumulator;
@@ -22,11 +22,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
22
22
  return E.error(new BodyParseFormDataError("Wrong boundary."));
23
23
  }
24
24
  let valueAccumulator = firstValueAccumulator;
25
- const startPart = Buffer.from(`\r\n--${boundary}`);
26
- const endMultiPart = Buffer.from(`\r\n--${boundary}--`);
25
+ const startPart = Buffer.from(`\r\n--${boundary}\r\n`);
26
+ const endMultiPart = Buffer.from(`\r\n--${boundary}--\r\n`);
27
27
  let currentBuffer = bufferStart;
28
28
  let size = 0;
29
- const keep = endMultiPart.length - 1;
29
+ const keep = endMultiPart.length;
30
30
  let currentStream = undefined;
31
31
  let fileQuantity = 0;
32
32
  let currentFileSize = undefined;
@@ -112,11 +112,6 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
112
112
  return await treatError(new BodyParseFormDataError("Buffer size exceeds limit."));
113
113
  }
114
114
  while (true) {
115
- const endMultiPartIndex = currentBuffer.indexOf(endMultiPart);
116
- if (endMultiPartIndex !== -1) {
117
- // check if buffer contain end of transmissions
118
- currentBuffer = currentBuffer.subarray(0, endMultiPartIndex);
119
- }
120
115
  const startPartIndex = currentBuffer.indexOf(startPart);
121
116
  const endHeaderPartIndex = currentBuffer.indexOf(endHeaderPart);
122
117
  if (startPartIndex !== -1 && endHeaderPartIndex !== -1) {
@@ -154,9 +149,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
154
149
  }
155
150
  }
156
151
  }
157
- const resultChunk = await flushReceiveChunk(currentBuffer);
158
- if (resultChunk !== true) {
159
- return await treatError(resultChunk);
152
+ if (currentBuffer.indexOf(endMultiPart) === -1) {
153
+ const resultChunk = await flushReceiveChunk(currentBuffer.subarray(0, 2));
154
+ if (resultChunk !== true) {
155
+ return await treatError(resultChunk);
156
+ }
160
157
  }
161
158
  valueAccumulator = await currentStream?.onEndPart(valueAccumulator) ?? valueAccumulator;
162
159
  return valueAccumulator;
@@ -2,10 +2,9 @@
2
2
 
3
3
  var http = require('http');
4
4
  var https = require('https');
5
- var index$3 = require('./hooks/index.cjs');
5
+ var index$2 = require('./hooks/index.cjs');
6
6
  var implementHttpServer = require('../../core/implementHttpServer.cjs');
7
7
  var utils = require('@duplojs/utils');
8
- var index$2 = require('../../core/defaultHooks/index.cjs');
9
8
  require('./bodyReaders/index.cjs');
10
9
  var index = require('./bodyReaders/text/index.cjs');
11
10
  var index$1 = require('./bodyReaders/formData/index.cjs');
@@ -25,7 +24,6 @@ function createHttpServer(hub, params) {
25
24
  index.createTextBodyReaderImplementation(httpServerParams),
26
25
  index$1.createFormDataBodyReaderImplementation(httpServerParams),
27
26
  ]);
28
- hub.addRouteHooks([index$2.initDefaultHook(hub, httpServerParams), index$3.nodeHook]);
29
27
  function whenUncaughtError(error, routerInitializationData) {
30
28
  const serverResponse = routerInitializationData.raw.response;
31
29
  if (!serverResponse.headersSent && !serverResponse.writableEnded) {
@@ -44,6 +42,7 @@ function createHttpServer(hub, params) {
44
42
  return implementHttpServer.implementHttpServer({
45
43
  hub,
46
44
  httpServerParams,
45
+ getInterfaceHooks: ({ hub, httpServerParams }) => [index$2.initNodeHook(hub, httpServerParams)],
47
46
  }, ({ httpServerParams, execRouteSystem }) => {
48
47
  const server = httpServerParams.https
49
48
  ? https.createServer(httpServerParams.https)
@@ -1,9 +1,8 @@
1
1
  import http from 'http';
2
2
  import https from 'https';
3
- import { nodeHook } from './hooks/index.mjs';
3
+ import { initNodeHook } from './hooks/index.mjs';
4
4
  import { implementHttpServer } from '../../core/implementHttpServer.mjs';
5
5
  import { O } from '@duplojs/utils';
6
- import { initDefaultHook } from '../../core/defaultHooks/index.mjs';
7
6
  import './bodyReaders/index.mjs';
8
7
  import { createTextBodyReaderImplementation } from './bodyReaders/text/index.mjs';
9
8
  import { createFormDataBodyReaderImplementation } from './bodyReaders/formData/index.mjs';
@@ -23,7 +22,6 @@ function createHttpServer(hub, params) {
23
22
  createTextBodyReaderImplementation(httpServerParams),
24
23
  createFormDataBodyReaderImplementation(httpServerParams),
25
24
  ]);
26
- hub.addRouteHooks([initDefaultHook(hub, httpServerParams), nodeHook]);
27
25
  function whenUncaughtError(error, routerInitializationData) {
28
26
  const serverResponse = routerInitializationData.raw.response;
29
27
  if (!serverResponse.headersSent && !serverResponse.writableEnded) {
@@ -42,6 +40,7 @@ function createHttpServer(hub, params) {
42
40
  return implementHttpServer({
43
41
  hub,
44
42
  httpServerParams,
43
+ getInterfaceHooks: ({ hub, httpServerParams }) => [initNodeHook(hub, httpServerParams)],
45
44
  }, ({ httpServerParams, execRouteSystem }) => {
46
45
  const server = httpServerParams.https
47
46
  ? https.createServer(httpServerParams.https)
@@ -1,47 +1,70 @@
1
1
  'use strict';
2
2
 
3
+ require('../../../core/response/index.cjs');
3
4
  require('../../../core/route/index.cjs');
5
+ var serverSentEvents = require('../../../core/serverSentEvents.cjs');
4
6
  var serverUtils = require('@duplojs/server-utils');
5
7
  var utils = require('@duplojs/utils');
6
8
  var node_fs = require('node:fs');
7
9
  var hooks = require('../../../core/route/hooks.cjs');
10
+ var serverSentEventsPredicted = require('../../../core/response/serverSentEventsPredicted.cjs');
8
11
 
9
- const nodeHook = hooks.createHookRouteLifeCycle({
10
- beforeSendResponse({ request, currentResponse, exit }) {
11
- request.raw.response.writeHead(Number(currentResponse.code), currentResponse.headers);
12
- return exit();
13
- },
14
- async sendResponse({ request, currentResponse, exit }) {
15
- const { response: rawResponse } = request.raw;
16
- const body = currentResponse.body;
17
- if (body instanceof Error) {
18
- rawResponse.write(body.toString());
19
- }
20
- else if (serverUtils.SF.isFileInterface(body)) {
21
- await new Promise((resolve, reject) => {
22
- node_fs.createReadStream(body.path)
23
- .pipe(request.raw.response
24
- .once("error", reject)
25
- .once("close", resolve));
26
- });
27
- }
28
- else if (typeof body === "object"
29
- || typeof body === "number"
30
- || typeof body === "boolean") {
31
- rawResponse.write(JSON.stringify(body));
32
- }
33
- else if (typeof body === "string") {
34
- rawResponse.write(body);
35
- }
36
- rawResponse.end();
37
- return exit();
38
- },
39
- async afterSendResponse({ request, next }) {
40
- if (request.filesAttache) {
41
- await Promise.all(utils.A.map(request.filesAttache, (path) => serverUtils.SF.remove(path)));
42
- }
43
- return next();
44
- },
45
- });
12
+ function initNodeHook(hub, serverParams) {
13
+ const isDev = hub.config.environment === "DEV";
14
+ return hooks.createHookRouteLifeCycle({
15
+ beforeSendResponse({ request, currentResponse, exit }) {
16
+ request.raw.response.writeHead(Number(currentResponse.code), currentResponse.headers);
17
+ return exit();
18
+ },
19
+ async sendResponse({ request, currentResponse, exit }) {
20
+ const { response: rawResponse, request: rawRequest } = request.raw;
21
+ if (currentResponse instanceof serverSentEventsPredicted.ServerSentEventsPredictedResponse) {
22
+ const handler = serverSentEvents.ServerSentEvents.init(currentResponse, {
23
+ lastId: typeof request.headers["last-event-id"] === "string"
24
+ ? request.headers["last-event-id"]
25
+ : null,
26
+ });
27
+ rawRequest.on("close", handler.abort);
28
+ void handler.start((value) => new Promise((resolve) => {
29
+ if (!rawResponse.write(value)) {
30
+ rawResponse.once("drain", resolve);
31
+ }
32
+ else {
33
+ resolve();
34
+ }
35
+ }), () => void rawResponse.end());
36
+ return exit();
37
+ }
38
+ const body = currentResponse.body;
39
+ if (body instanceof Error) {
40
+ rawResponse.write(body.toString());
41
+ }
42
+ else if (serverUtils.SF.isFileInterface(body)) {
43
+ await new Promise((resolve, reject) => {
44
+ node_fs.createReadStream(body.path)
45
+ .pipe(request.raw.response
46
+ .once("error", reject)
47
+ .once("close", resolve));
48
+ });
49
+ }
50
+ else if (typeof body === "object"
51
+ || typeof body === "number"
52
+ || typeof body === "boolean") {
53
+ rawResponse.write(JSON.stringify(body));
54
+ }
55
+ else if (typeof body === "string") {
56
+ rawResponse.write(body);
57
+ }
58
+ rawResponse.end();
59
+ return exit();
60
+ },
61
+ async afterSendResponse({ request, next }) {
62
+ if (request.filesAttache) {
63
+ await Promise.all(utils.A.map(request.filesAttache, (path) => serverUtils.SF.remove(path)));
64
+ }
65
+ return next();
66
+ },
67
+ });
68
+ }
46
69
 
47
- exports.nodeHook = nodeHook;
70
+ exports.initNodeHook = initNodeHook;
@@ -1,5 +1,7 @@
1
- export declare const nodeHook: {
2
- beforeSendResponse({ request, currentResponse, exit }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>): import("../../../core/route").RouteHookExit;
3
- sendResponse({ request, currentResponse, exit }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>): Promise<import("../../../core/route").RouteHookExit>;
4
- afterSendResponse({ request, next }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>): Promise<import("../../../core/route").RouteHookNext>;
1
+ import { type Hub } from "../../../core/hub";
2
+ import { type HttpServerParams } from "../../../core/types";
3
+ export declare function initNodeHook(hub: Hub, serverParams: HttpServerParams): {
4
+ readonly beforeSendResponse: ({ request, currentResponse, exit }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>) => import("../../../core/route").RouteHookExit;
5
+ readonly sendResponse: ({ request, currentResponse, exit }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>) => Promise<import("../../../core/route").RouteHookExit>;
6
+ readonly afterSendResponse: ({ request, next }: import("../../../core/route").RouteHookParamsAfter<import("../../../core/request").Request>) => Promise<import("../../../core/route").RouteHookNext>;
5
7
  };
@@ -1,45 +1,68 @@
1
+ import '../../../core/response/index.mjs';
1
2
  import '../../../core/route/index.mjs';
3
+ import { ServerSentEvents } from '../../../core/serverSentEvents.mjs';
2
4
  import { SF } from '@duplojs/server-utils';
3
5
  import { A } from '@duplojs/utils';
4
6
  import { createReadStream } from 'node:fs';
5
7
  import { createHookRouteLifeCycle } from '../../../core/route/hooks.mjs';
8
+ import { ServerSentEventsPredictedResponse } from '../../../core/response/serverSentEventsPredicted.mjs';
6
9
 
7
- const nodeHook = createHookRouteLifeCycle({
8
- beforeSendResponse({ request, currentResponse, exit }) {
9
- request.raw.response.writeHead(Number(currentResponse.code), currentResponse.headers);
10
- return exit();
11
- },
12
- async sendResponse({ request, currentResponse, exit }) {
13
- const { response: rawResponse } = request.raw;
14
- const body = currentResponse.body;
15
- if (body instanceof Error) {
16
- rawResponse.write(body.toString());
17
- }
18
- else if (SF.isFileInterface(body)) {
19
- await new Promise((resolve, reject) => {
20
- createReadStream(body.path)
21
- .pipe(request.raw.response
22
- .once("error", reject)
23
- .once("close", resolve));
24
- });
25
- }
26
- else if (typeof body === "object"
27
- || typeof body === "number"
28
- || typeof body === "boolean") {
29
- rawResponse.write(JSON.stringify(body));
30
- }
31
- else if (typeof body === "string") {
32
- rawResponse.write(body);
33
- }
34
- rawResponse.end();
35
- return exit();
36
- },
37
- async afterSendResponse({ request, next }) {
38
- if (request.filesAttache) {
39
- await Promise.all(A.map(request.filesAttache, (path) => SF.remove(path)));
40
- }
41
- return next();
42
- },
43
- });
10
+ function initNodeHook(hub, serverParams) {
11
+ const isDev = hub.config.environment === "DEV";
12
+ return createHookRouteLifeCycle({
13
+ beforeSendResponse({ request, currentResponse, exit }) {
14
+ request.raw.response.writeHead(Number(currentResponse.code), currentResponse.headers);
15
+ return exit();
16
+ },
17
+ async sendResponse({ request, currentResponse, exit }) {
18
+ const { response: rawResponse, request: rawRequest } = request.raw;
19
+ if (currentResponse instanceof ServerSentEventsPredictedResponse) {
20
+ const handler = ServerSentEvents.init(currentResponse, {
21
+ lastId: typeof request.headers["last-event-id"] === "string"
22
+ ? request.headers["last-event-id"]
23
+ : null,
24
+ });
25
+ rawRequest.on("close", handler.abort);
26
+ void handler.start((value) => new Promise((resolve) => {
27
+ if (!rawResponse.write(value)) {
28
+ rawResponse.once("drain", resolve);
29
+ }
30
+ else {
31
+ resolve();
32
+ }
33
+ }), () => void rawResponse.end());
34
+ return exit();
35
+ }
36
+ const body = currentResponse.body;
37
+ if (body instanceof Error) {
38
+ rawResponse.write(body.toString());
39
+ }
40
+ else if (SF.isFileInterface(body)) {
41
+ await new Promise((resolve, reject) => {
42
+ createReadStream(body.path)
43
+ .pipe(request.raw.response
44
+ .once("error", reject)
45
+ .once("close", resolve));
46
+ });
47
+ }
48
+ else if (typeof body === "object"
49
+ || typeof body === "number"
50
+ || typeof body === "boolean") {
51
+ rawResponse.write(JSON.stringify(body));
52
+ }
53
+ else if (typeof body === "string") {
54
+ rawResponse.write(body);
55
+ }
56
+ rawResponse.end();
57
+ return exit();
58
+ },
59
+ async afterSendResponse({ request, next }) {
60
+ if (request.filesAttache) {
61
+ await Promise.all(A.map(request.filesAttache, (path) => SF.remove(path)));
62
+ }
63
+ return next();
64
+ },
65
+ });
66
+ }
44
67
 
45
- export { nodeHook };
68
+ export { initNodeHook };
@@ -15,7 +15,7 @@ var index$2 = require('./bodyReaders/text/index.cjs');
15
15
 
16
16
  exports.createInterfacesNodeLibKind = kind.createInterfacesNodeLibKind;
17
17
  exports.createHttpServer = createHttpServer.createHttpServer;
18
- exports.nodeHook = index.nodeHook;
18
+ exports.initNodeHook = index.initNodeHook;
19
19
  exports.BodyParseFormDataError = error.BodyParseFormDataError;
20
20
  exports.readRequestFormData = readRequestFormData.readRequestFormData;
21
21
  exports.createFormDataBodyReaderImplementation = index$1.createFormDataBodyReaderImplementation;
@@ -1,7 +1,7 @@
1
1
  import './types/index.mjs';
2
2
  export { createInterfacesNodeLibKind } from './kind.mjs';
3
3
  export { createHttpServer } from './createHttpServer.mjs';
4
- export { nodeHook } from './hooks/index.mjs';
4
+ export { initNodeHook } from './hooks/index.mjs';
5
5
  import './bodyReaders/index.mjs';
6
6
  export { BodyParseFormDataError } from './bodyReaders/formData/error.mjs';
7
7
  export { readRequestFormData } from './bodyReaders/formData/readRequestFormData.mjs';
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@duplojs/utils');
4
+
5
+ function createCacheControlResponseHeader(directives) {
6
+ return utils.pipe([
7
+ utils.O.entry("max-age", directives.maxAge),
8
+ utils.O.entry("s-maxage", directives.sMaxAge),
9
+ utils.O.entry("public", directives.public),
10
+ utils.O.entry("private", directives.private),
11
+ utils.O.entry("no-cache", directives.noCache),
12
+ utils.O.entry("no-store", directives.noStore),
13
+ utils.O.entry("no-transform", directives.noTransform),
14
+ utils.O.entry("must-revalidate", directives.mustRevalidate),
15
+ utils.O.entry("proxy-revalidate", directives.proxyRevalidate),
16
+ utils.O.entry("immutable", directives.immutable),
17
+ utils.O.entry("stale-while-revalidate", directives.staleWhileRevalidate),
18
+ utils.O.entry("stale-if-error", directives.staleIfError),
19
+ utils.O.entry("must-understand", directives.mustUnderstand),
20
+ ], utils.A.concat(directives.extensions ? utils.O.entries(directives.extensions) : []), utils.A.reduce(utils.A.reduceFrom([]), ({ element: [key, value], lastValue, nextPush, next }) => {
21
+ if (value === true) {
22
+ return nextPush(lastValue, key);
23
+ }
24
+ else if (typeof value === "number"
25
+ && Number.isFinite(value)
26
+ && value >= 0) {
27
+ return nextPush(lastValue, `${key}=${Math.trunc(value)}`);
28
+ }
29
+ else if (value instanceof Array
30
+ && utils.A.minElements(value, 1)) {
31
+ return nextPush(lastValue, `${key}="${utils.A.join(value, ",")}"`);
32
+ }
33
+ else if (value !== ""
34
+ && typeof value === "string") {
35
+ return nextPush(lastValue, `${key}="${value}"`);
36
+ }
37
+ else {
38
+ return next(lastValue);
39
+ }
40
+ }), utils.A.join(","));
41
+ }
42
+
43
+ exports.createCacheControlResponseHeader = createCacheControlResponseHeader;
@@ -0,0 +1,2 @@
1
+ import type { CacheControlDirectives } from "./types";
2
+ export declare function createCacheControlResponseHeader(directives: CacheControlDirectives): string;
@@ -0,0 +1,41 @@
1
+ import { pipe, O, A } from '@duplojs/utils';
2
+
3
+ function createCacheControlResponseHeader(directives) {
4
+ return pipe([
5
+ O.entry("max-age", directives.maxAge),
6
+ O.entry("s-maxage", directives.sMaxAge),
7
+ O.entry("public", directives.public),
8
+ O.entry("private", directives.private),
9
+ O.entry("no-cache", directives.noCache),
10
+ O.entry("no-store", directives.noStore),
11
+ O.entry("no-transform", directives.noTransform),
12
+ O.entry("must-revalidate", directives.mustRevalidate),
13
+ O.entry("proxy-revalidate", directives.proxyRevalidate),
14
+ O.entry("immutable", directives.immutable),
15
+ O.entry("stale-while-revalidate", directives.staleWhileRevalidate),
16
+ O.entry("stale-if-error", directives.staleIfError),
17
+ O.entry("must-understand", directives.mustUnderstand),
18
+ ], A.concat(directives.extensions ? O.entries(directives.extensions) : []), A.reduce(A.reduceFrom([]), ({ element: [key, value], lastValue, nextPush, next }) => {
19
+ if (value === true) {
20
+ return nextPush(lastValue, key);
21
+ }
22
+ else if (typeof value === "number"
23
+ && Number.isFinite(value)
24
+ && value >= 0) {
25
+ return nextPush(lastValue, `${key}=${Math.trunc(value)}`);
26
+ }
27
+ else if (value instanceof Array
28
+ && A.minElements(value, 1)) {
29
+ return nextPush(lastValue, `${key}="${A.join(value, ",")}"`);
30
+ }
31
+ else if (value !== ""
32
+ && typeof value === "string") {
33
+ return nextPush(lastValue, `${key}="${value}"`);
34
+ }
35
+ else {
36
+ return next(lastValue);
37
+ }
38
+ }), A.join(","));
39
+ }
40
+
41
+ export { createCacheControlResponseHeader };
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ var createResponseHeader = require('./createResponseHeader.cjs');
4
+ require('../../core/route/index.cjs');
5
+ var hooks = require('../../core/route/hooks.cjs');
6
+
7
+ const eligibleCodeRegex = /^(?:2|3)/;
8
+ function createCacheControllerHooks(params) {
9
+ const cacheControl = params
10
+ ? createResponseHeader.createCacheControlResponseHeader(params)
11
+ : null;
12
+ return hooks.createHookRouteLifeCycle({
13
+ beforeSendResponse: ({ currentResponse, next }) => {
14
+ if (cacheControl
15
+ && eligibleCodeRegex.test(currentResponse.code)) {
16
+ currentResponse.setHeader("cache-control", cacheControl);
17
+ }
18
+ return next();
19
+ },
20
+ });
21
+ }
22
+
23
+ exports.createCacheControllerHooks = createCacheControllerHooks;
@@ -0,0 +1,4 @@
1
+ import type { CacheControlDirectives } from "./types";
2
+ export declare function createCacheControllerHooks(params?: CacheControlDirectives): {
3
+ readonly beforeSendResponse: ({ currentResponse, next }: import("../../core/route").RouteHookParamsAfter<import("../../core/request").Request>) => import("../../core/route").RouteHookNext;
4
+ };
@@ -0,0 +1,21 @@
1
+ import { createCacheControlResponseHeader } from './createResponseHeader.mjs';
2
+ import '../../core/route/index.mjs';
3
+ import { createHookRouteLifeCycle } from '../../core/route/hooks.mjs';
4
+
5
+ const eligibleCodeRegex = /^(?:2|3)/;
6
+ function createCacheControllerHooks(params) {
7
+ const cacheControl = params
8
+ ? createCacheControlResponseHeader(params)
9
+ : null;
10
+ return createHookRouteLifeCycle({
11
+ beforeSendResponse: ({ currentResponse, next }) => {
12
+ if (cacheControl
13
+ && eligibleCodeRegex.test(currentResponse.code)) {
14
+ currentResponse.setHeader("cache-control", cacheControl);
15
+ }
16
+ return next();
17
+ },
18
+ });
19
+ }
20
+
21
+ export { createCacheControllerHooks };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ var hooks = require('./hooks.cjs');
4
+ require('./types/index.cjs');
5
+ var createResponseHeader = require('./createResponseHeader.cjs');
6
+
7
+
8
+
9
+ exports.createCacheControllerHooks = hooks.createCacheControllerHooks;
10
+ exports.createCacheControlResponseHeader = createResponseHeader.createCacheControlResponseHeader;
@@ -0,0 +1,3 @@
1
+ export * from "./hooks";
2
+ export * from "./types";
3
+ export * from "./createResponseHeader";
@@ -0,0 +1,3 @@
1
+ export { createCacheControllerHooks } from './hooks.mjs';
2
+ import './types/index.mjs';
3
+ export { createCacheControlResponseHeader } from './createResponseHeader.mjs';
@@ -0,0 +1,16 @@
1
+ export interface CacheControlDirectives {
2
+ maxAge?: number;
3
+ sMaxAge?: number;
4
+ public?: true;
5
+ private?: true | string[];
6
+ noCache?: true | string[];
7
+ noStore?: true;
8
+ noTransform?: true;
9
+ mustRevalidate?: true;
10
+ proxyRevalidate?: true;
11
+ immutable?: true;
12
+ staleWhileRevalidate?: number;
13
+ staleIfError?: number;
14
+ mustUnderstand?: true;
15
+ extensions?: Record<string, string>;
16
+ }
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ require('./cacheControlDirectives.cjs');
4
+
@@ -0,0 +1 @@
1
+ export * from "./cacheControlDirectives";
@@ -0,0 +1 @@
1
+ import './cacheControlDirectives.mjs';
@@ -2,6 +2,7 @@
2
2
 
3
3
  require('../../core/steps/index.cjs');
4
4
  var utils = require('@duplojs/utils');
5
+ require('../../core/response/index.cjs');
5
6
  var metadata = require('./metadata.cjs');
6
7
  var identifier = require('../../core/steps/identifier.cjs');
7
8
  var process = require('../../core/steps/process.cjs');
@@ -10,6 +11,7 @@ var presetChecker = require('../../core/steps/presetChecker.cjs');
10
11
  var checker = require('../../core/steps/checker.cjs');
11
12
  var cut = require('../../core/steps/cut.cjs');
12
13
  var handler = require('../../core/steps/handler.cjs');
14
+ var contract = require('../../core/response/contract.cjs');
13
15
 
14
16
  function aggregateStepContract(steps, params) {
15
17
  const filteredStep = utils.A.filter(steps, (step) => utils.A.find(step.definition.metadata, metadata.IgnoreByCodeGeneratorMetadata.is) === undefined);
@@ -55,11 +57,16 @@ function aggregateStepContract(steps, params) {
55
57
  cut.cutStepKind,
56
58
  handler.handlerStepKind,
57
59
  ]), ({ definition }) => definition.responseContract)
58
- .exhaustive()), utils.A.map(({ code, information, body }) => utils.DP.object({
60
+ .exhaustive()), utils.A.map(utils.innerPipe(utils.P.when(contract.ResponseContract.contractKind.has, ({ code, information, body }) => utils.DP.object({
59
61
  code: utils.DP.literal(code),
60
62
  information: utils.DP.literal(information),
61
63
  body,
62
- })), utils.A.concat(processContracts.endpointContract));
64
+ })), utils.P.when(contract.ResponseContract.serverSentEventsContractKind.has, ({ code, information, body, events }) => utils.DP.object({
65
+ code: utils.DP.literal(code),
66
+ information: utils.DP.literal(information),
67
+ body,
68
+ events: utils.DP.object(events),
69
+ })), utils.P.exhaustive)), utils.A.concat(processContracts.endpointContract));
63
70
  return {
64
71
  entrypointContract,
65
72
  endpointContract,