@duplojs/http 0.7.4 → 0.8.5

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 (154) 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.cjs +1 -0
  63. package/dist/core/request/bodyController/formData.d.ts +4 -2
  64. package/dist/core/request/bodyController/formData.mjs +1 -0
  65. package/dist/core/request/bodyController/index.cjs +4 -0
  66. package/dist/core/request/bodyController/index.d.ts +1 -0
  67. package/dist/core/request/bodyController/index.mjs +2 -1
  68. package/dist/core/request/index.cjs +5 -0
  69. package/dist/core/request/index.d.ts +1 -1
  70. package/dist/core/request/index.mjs +6 -1
  71. package/dist/core/response/contract.cjs +17 -4
  72. package/dist/core/response/contract.d.ts +19 -4
  73. package/dist/core/response/contract.mjs +17 -4
  74. package/dist/core/response/index.cjs +2 -0
  75. package/dist/core/response/index.d.ts +1 -0
  76. package/dist/core/response/index.mjs +1 -0
  77. package/dist/core/response/serverSentEventsPredicted.cjs +23 -0
  78. package/dist/core/response/serverSentEventsPredicted.d.ts +14 -0
  79. package/dist/core/response/serverSentEventsPredicted.mjs +21 -0
  80. package/dist/core/route/hooks.cjs +9 -0
  81. package/dist/core/route/hooks.d.ts +10 -9
  82. package/dist/core/route/hooks.mjs +9 -1
  83. package/dist/core/route/index.cjs +1 -0
  84. package/dist/core/route/index.mjs +1 -1
  85. package/dist/core/router/buildSystemRoute.cjs +33 -0
  86. package/dist/core/router/buildSystemRoute.d.ts +11 -0
  87. package/dist/core/router/buildSystemRoute.mjs +31 -0
  88. package/dist/core/router/decodeUrl.cjs +5 -4
  89. package/dist/core/router/decodeUrl.d.ts +1 -1
  90. package/dist/core/router/decodeUrl.mjs +5 -4
  91. package/dist/core/router/index.cjs +24 -23
  92. package/dist/core/router/index.d.ts +1 -0
  93. package/dist/core/router/index.mjs +25 -25
  94. package/dist/core/serverSentEvents.cjs +96 -0
  95. package/dist/core/serverSentEvents.d.ts +33 -0
  96. package/dist/core/serverSentEvents.mjs +96 -0
  97. package/dist/core/steps/cut.d.ts +2 -2
  98. package/dist/core/steps/handler.d.ts +10 -5
  99. package/dist/interfaces/node/bodyReaders/formData/index.cjs +34 -14
  100. package/dist/interfaces/node/bodyReaders/formData/index.mjs +35 -15
  101. package/dist/interfaces/node/bodyReaders/formData/readRequestFormData.cjs +18 -12
  102. package/dist/interfaces/node/bodyReaders/formData/readRequestFormData.d.ts +2 -1
  103. package/dist/interfaces/node/bodyReaders/formData/readRequestFormData.mjs +18 -12
  104. package/dist/interfaces/node/createHttpServer.cjs +2 -3
  105. package/dist/interfaces/node/createHttpServer.mjs +2 -3
  106. package/dist/interfaces/node/hooks/index.cjs +61 -38
  107. package/dist/interfaces/node/hooks/index.d.ts +6 -4
  108. package/dist/interfaces/node/hooks/index.mjs +61 -38
  109. package/dist/interfaces/node/index.cjs +1 -1
  110. package/dist/interfaces/node/index.mjs +1 -1
  111. package/dist/plugins/cacheController/createResponseHeader.cjs +43 -0
  112. package/dist/plugins/cacheController/createResponseHeader.d.ts +2 -0
  113. package/dist/plugins/cacheController/createResponseHeader.mjs +41 -0
  114. package/dist/plugins/cacheController/hooks.cjs +23 -0
  115. package/dist/plugins/cacheController/hooks.d.ts +4 -0
  116. package/dist/plugins/cacheController/hooks.mjs +21 -0
  117. package/dist/plugins/cacheController/index.cjs +10 -0
  118. package/dist/plugins/cacheController/index.d.ts +3 -0
  119. package/dist/plugins/cacheController/index.mjs +3 -0
  120. package/dist/plugins/cacheController/types/cacheControlDirectives.cjs +2 -0
  121. package/dist/plugins/cacheController/types/cacheControlDirectives.d.ts +16 -0
  122. package/dist/plugins/cacheController/types/cacheControlDirectives.mjs +1 -0
  123. package/dist/plugins/cacheController/types/index.cjs +4 -0
  124. package/dist/plugins/cacheController/types/index.d.ts +1 -0
  125. package/dist/plugins/cacheController/types/index.mjs +1 -0
  126. package/dist/plugins/codeGenerator/aggregateStepContract.cjs +9 -2
  127. package/dist/plugins/codeGenerator/aggregateStepContract.d.ts +1 -1
  128. package/dist/plugins/codeGenerator/aggregateStepContract.mjs +10 -3
  129. package/dist/plugins/codeGenerator/plugin.cjs +4 -4
  130. package/dist/plugins/codeGenerator/plugin.mjs +1 -1
  131. package/dist/plugins/openApiGenerator/aggregateStepContract.d.ts +2 -7
  132. package/dist/plugins/openApiGenerator/routeToOpenApi.cjs +46 -8
  133. package/dist/plugins/openApiGenerator/routeToOpenApi.d.ts +2 -2
  134. package/dist/plugins/openApiGenerator/routeToOpenApi.mjs +46 -8
  135. package/dist/plugins/openApiGenerator/types/endpointResponse.d.ts +7 -3
  136. package/dist/plugins/static/index.cjs +14 -0
  137. package/dist/plugins/static/index.d.ts +3 -0
  138. package/dist/plugins/static/index.mjs +3 -0
  139. package/dist/plugins/static/kind.cjs +9 -0
  140. package/dist/plugins/static/kind.d.ts +6 -0
  141. package/dist/plugins/static/kind.mjs +7 -0
  142. package/dist/plugins/static/makeRouteFile.cjs +62 -0
  143. package/dist/plugins/static/makeRouteFile.d.ts +48 -0
  144. package/dist/plugins/static/makeRouteFile.mjs +58 -0
  145. package/dist/plugins/static/makeRouteFolder.cjs +67 -0
  146. package/dist/plugins/static/makeRouteFolder.d.ts +39 -0
  147. package/dist/plugins/static/makeRouteFolder.mjs +65 -0
  148. package/dist/plugins/static/plugin.cjs +53 -0
  149. package/dist/plugins/static/plugin.d.ts +26 -0
  150. package/dist/plugins/static/plugin.mjs +50 -0
  151. package/package.json +18 -7
  152. /package/dist/plugins/codeGenerator/{typescriptTransfomer.cjs → typescriptTransformer.cjs} +0 -0
  153. /package/dist/plugins/codeGenerator/{typescriptTransfomer.d.ts → typescriptTransformer.d.ts} +0 -0
  154. /package/dist/plugins/codeGenerator/{typescriptTransfomer.mjs → typescriptTransformer.mjs} +0 -0
@@ -24,14 +24,15 @@ 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;
35
+ let currentTextFieldSize = undefined;
35
36
  const checkSize = (receivedChunk) => {
36
37
  size += receivedChunk.length;
37
38
  return size > params.maxBodySize
@@ -61,6 +62,7 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
61
62
  }
62
63
  if (header.filename !== undefined) {
63
64
  currentFileSize = 0;
65
+ currentTextFieldSize = undefined;
64
66
  fileQuantity++;
65
67
  if (fileQuantity > params.maxFileQuantity) {
66
68
  return new error.BodyParseFormDataError("File quantity exceeds limit.");
@@ -72,6 +74,7 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
72
74
  }
73
75
  else {
74
76
  currentFileSize = undefined;
77
+ currentTextFieldSize = 0;
75
78
  }
76
79
  const newStream = await onReceiveHeader(header);
77
80
  if (newStream instanceof Error) {
@@ -93,10 +96,16 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
93
96
  }
94
97
  if (typeof currentFileSize === "number") {
95
98
  currentFileSize += chunk.length;
96
- if (params.fileMaxSize !== undefined && currentFileSize > params.fileMaxSize) {
99
+ if (currentFileSize > params.fileMaxSize) {
97
100
  return new error.BodyParseFormDataError("File size exceeds limit.");
98
101
  }
99
102
  }
103
+ if (typeof currentTextFieldSize === "number") {
104
+ currentTextFieldSize += chunk.length;
105
+ if (currentTextFieldSize > params.textFieldMaxSize) {
106
+ return new error.BodyParseFormDataError("Text field size exceeds limit.");
107
+ }
108
+ }
100
109
  await currentStream.onReceiveChunk(chunk);
101
110
  return true;
102
111
  };
@@ -114,11 +123,6 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
114
123
  return await treatError(new error.BodyParseFormDataError("Buffer size exceeds limit."));
115
124
  }
116
125
  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
126
  const startPartIndex = currentBuffer.indexOf(startPart);
123
127
  const endHeaderPartIndex = currentBuffer.indexOf(endHeaderPart);
124
128
  if (startPartIndex !== -1 && endHeaderPartIndex !== -1) {
@@ -156,9 +160,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
156
160
  }
157
161
  }
158
162
  }
159
- const resultChunk = await flushReceiveChunk(currentBuffer);
160
- if (resultChunk !== true) {
161
- return await treatError(resultChunk);
163
+ if (currentBuffer.indexOf(endMultiPart) === -1) {
164
+ const resultChunk = await flushReceiveChunk(currentBuffer.subarray(0, 2));
165
+ if (resultChunk !== true) {
166
+ return await treatError(resultChunk);
167
+ }
162
168
  }
163
169
  valueAccumulator = await currentStream?.onEndPart(valueAccumulator) ?? valueAccumulator;
164
170
  return valueAccumulator;
@@ -14,7 +14,8 @@ export interface ReadRequestFormDataParams {
14
14
  maxFileQuantity: number;
15
15
  maxBufferSize: number;
16
16
  maxKeyLength: number;
17
- fileMaxSize?: number;
17
+ fileMaxSize: number;
18
+ textFieldMaxSize: number;
18
19
  mimeType?: RegExp;
19
20
  }
20
21
  export declare function readRequestFormData<GenericValueAccumulator extends unknown, GenericOutputHeader extends E.Left = never>(request: http.IncomingMessage, firstValueAccumulator: GenericValueAccumulator, params: ReadRequestFormDataParams, onReceiveHeader: (header: HeaderPartInformation) => MaybePromise<ReadRequestFormDataStreamChunkEvent<GenericValueAccumulator> | Error>): Promise<E.Left<"server-error", unknown> | GenericOutputHeader | E.Error<Error> | GenericValueAccumulator>;
@@ -22,14 +22,15 @@ 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;
33
+ let currentTextFieldSize = undefined;
33
34
  const checkSize = (receivedChunk) => {
34
35
  size += receivedChunk.length;
35
36
  return size > params.maxBodySize
@@ -59,6 +60,7 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
59
60
  }
60
61
  if (header.filename !== undefined) {
61
62
  currentFileSize = 0;
63
+ currentTextFieldSize = undefined;
62
64
  fileQuantity++;
63
65
  if (fileQuantity > params.maxFileQuantity) {
64
66
  return new BodyParseFormDataError("File quantity exceeds limit.");
@@ -70,6 +72,7 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
70
72
  }
71
73
  else {
72
74
  currentFileSize = undefined;
75
+ currentTextFieldSize = 0;
73
76
  }
74
77
  const newStream = await onReceiveHeader(header);
75
78
  if (newStream instanceof Error) {
@@ -91,10 +94,16 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
91
94
  }
92
95
  if (typeof currentFileSize === "number") {
93
96
  currentFileSize += chunk.length;
94
- if (params.fileMaxSize !== undefined && currentFileSize > params.fileMaxSize) {
97
+ if (currentFileSize > params.fileMaxSize) {
95
98
  return new BodyParseFormDataError("File size exceeds limit.");
96
99
  }
97
100
  }
101
+ if (typeof currentTextFieldSize === "number") {
102
+ currentTextFieldSize += chunk.length;
103
+ if (currentTextFieldSize > params.textFieldMaxSize) {
104
+ return new BodyParseFormDataError("Text field size exceeds limit.");
105
+ }
106
+ }
98
107
  await currentStream.onReceiveChunk(chunk);
99
108
  return true;
100
109
  };
@@ -112,11 +121,6 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
112
121
  return await treatError(new BodyParseFormDataError("Buffer size exceeds limit."));
113
122
  }
114
123
  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
124
  const startPartIndex = currentBuffer.indexOf(startPart);
121
125
  const endHeaderPartIndex = currentBuffer.indexOf(endHeaderPart);
122
126
  if (startPartIndex !== -1 && endHeaderPartIndex !== -1) {
@@ -154,9 +158,11 @@ async function readRequestFormData(request, firstValueAccumulator, params, onRec
154
158
  }
155
159
  }
156
160
  }
157
- const resultChunk = await flushReceiveChunk(currentBuffer);
158
- if (resultChunk !== true) {
159
- return await treatError(resultChunk);
161
+ if (currentBuffer.indexOf(endMultiPart) === -1) {
162
+ const resultChunk = await flushReceiveChunk(currentBuffer.subarray(0, 2));
163
+ if (resultChunk !== true) {
164
+ return await treatError(resultChunk);
165
+ }
160
166
  }
161
167
  valueAccumulator = await currentStream?.onEndPart(valueAccumulator) ?? valueAccumulator;
162
168
  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';