@lakutata/entrypoint 3.0.0 → 3.1.0

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 (129) hide show
  1. package/README.md +39 -26
  2. package/README.zh-CN.md +182 -0
  3. package/dist/cjs/Entrypoint.d.ts +13 -7
  4. package/dist/cjs/Entrypoint.js +12 -6
  5. package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.d.ts +3 -2
  6. package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.js +3 -2
  7. package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +2 -1
  8. package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.js +2 -1
  9. package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.d.ts +3 -2
  10. package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.js +8 -2
  11. package/dist/cjs/adapter/express/Responders.d.ts +2 -1
  12. package/dist/cjs/adapter/express/Responders.js +4 -2
  13. package/dist/cjs/adapter/express/StaticUI.d.ts +2 -1
  14. package/dist/cjs/adapter/express/StaticUI.js +2 -1
  15. package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.d.ts +2 -1
  16. package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.js +4 -1
  17. package/dist/cjs/adapter/fastify/Responders.d.ts +2 -1
  18. package/dist/cjs/adapter/fastify/Responders.js +4 -2
  19. package/dist/cjs/adapter/http/HTTPServiceEntrypoint.d.ts +4 -3
  20. package/dist/cjs/adapter/http/HTTPServiceEntrypoint.js +10 -22
  21. package/dist/cjs/adapter/http/HTTPServiceProxy.d.ts +190 -0
  22. package/dist/cjs/adapter/http/HTTPServiceProxy.js +371 -0
  23. package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +11 -7
  24. package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +15 -26
  25. package/dist/cjs/adapter/schedule/ScheduleEntrypoint.d.ts +2 -1
  26. package/dist/cjs/adapter/schedule/ScheduleEntrypoint.js +12 -5
  27. package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +2 -1
  28. package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.js +2 -1
  29. package/dist/cjs/channel/BuiltinChannels.js +4 -2
  30. package/dist/cjs/channel/EntrypointAdapter.d.ts +2 -2
  31. package/dist/cjs/decorators/HTTPAction.d.ts +5 -5
  32. package/dist/cjs/decorators/Schedule.d.ts +4 -2
  33. package/dist/cjs/decorators/Schedule.js +3 -2
  34. package/dist/cjs/decorators/ServiceAction.d.ts +12 -8
  35. package/dist/cjs/decorators/http/DELETE.d.ts +5 -5
  36. package/dist/cjs/decorators/http/GET.d.ts +7 -7
  37. package/dist/cjs/decorators/http/HEAD.d.ts +9 -9
  38. package/dist/cjs/decorators/http/OPTIONS.d.ts +8 -7
  39. package/dist/cjs/decorators/http/PATCH.d.ts +5 -5
  40. package/dist/cjs/decorators/http/POST.d.ts +5 -5
  41. package/dist/cjs/decorators/http/PUT.d.ts +7 -7
  42. package/dist/cjs/exceptions/AccessDeniedException.d.ts +7 -1
  43. package/dist/cjs/exceptions/AccessDeniedException.js +8 -3
  44. package/dist/cjs/exceptions/EntrypointStoppedException.d.ts +2 -1
  45. package/dist/cjs/exceptions/EntrypointStoppedException.js +2 -1
  46. package/dist/cjs/exceptions/InvalidActionGroupException.d.ts +4 -0
  47. package/dist/cjs/exceptions/InvalidActionGroupException.js +4 -0
  48. package/dist/cjs/exceptions/ServiceUnavailableException.d.ts +15 -0
  49. package/dist/cjs/exceptions/ServiceUnavailableException.js +18 -0
  50. package/dist/cjs/exports/Entrypoint.d.ts +3 -0
  51. package/dist/cjs/exports/Entrypoint.js +6 -1
  52. package/dist/cjs/lib/AccessControl.d.ts +2 -1
  53. package/dist/cjs/lib/AccessControl.js +2 -1
  54. package/dist/cjs/lib/AccessControlRule.d.ts +2 -1
  55. package/dist/cjs/lib/AccessControlRule.js +2 -1
  56. package/dist/cjs/lib/ExplicitStatus.d.ts +11 -0
  57. package/dist/cjs/lib/ExplicitStatus.js +22 -0
  58. package/dist/cjs/lib/Middleware.d.ts +2 -1
  59. package/dist/cjs/lib/Middleware.js +2 -1
  60. package/dist/cjs/lib/Preflight.d.ts +8 -0
  61. package/dist/cjs/lib/Preflight.js +13 -0
  62. package/dist/cjs/lib/ReadBody.d.ts +9 -0
  63. package/dist/cjs/lib/ReadBody.js +25 -0
  64. package/dist/cjs/lib/pattern/FlattenPattern.d.ts +14 -0
  65. package/dist/cjs/lib/pattern/FlattenPattern.js +59 -0
  66. package/dist/esm/Entrypoint.js +12 -6
  67. package/dist/esm/adapter/commander/CommanderCLIEntrypoint.js +3 -2
  68. package/dist/esm/adapter/electron/ElectronIPCServiceEntrypoint.js +2 -1
  69. package/dist/esm/adapter/express/ExpressHTTPEntrypoint.js +8 -2
  70. package/dist/esm/adapter/express/Responders.js +4 -2
  71. package/dist/esm/adapter/express/StaticUI.js +2 -1
  72. package/dist/esm/adapter/fastify/FastifyHTTPEntrypoint.js +4 -1
  73. package/dist/esm/adapter/fastify/Responders.js +4 -2
  74. package/dist/esm/adapter/http/HTTPServiceEntrypoint.js +9 -21
  75. package/dist/esm/adapter/http/HTTPServiceProxy.js +366 -0
  76. package/dist/esm/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +14 -25
  77. package/dist/esm/adapter/schedule/ScheduleEntrypoint.js +12 -5
  78. package/dist/esm/adapter/socket.io/SocketIOServiceEntrypoint.js +2 -1
  79. package/dist/esm/channel/BuiltinChannels.js +4 -2
  80. package/dist/esm/decorators/Schedule.js +3 -2
  81. package/dist/esm/exceptions/AccessDeniedException.js +8 -3
  82. package/dist/esm/exceptions/EntrypointStoppedException.js +2 -1
  83. package/dist/esm/exceptions/InvalidActionGroupException.js +4 -0
  84. package/dist/esm/exceptions/ServiceUnavailableException.js +14 -0
  85. package/dist/esm/exports/Entrypoint.js +3 -0
  86. package/dist/esm/lib/AccessControl.js +2 -1
  87. package/dist/esm/lib/AccessControlRule.js +2 -1
  88. package/dist/esm/lib/ExplicitStatus.js +18 -0
  89. package/dist/esm/lib/Middleware.js +2 -1
  90. package/dist/esm/lib/Preflight.js +10 -0
  91. package/dist/esm/lib/ReadBody.js +22 -0
  92. package/dist/esm/lib/pattern/FlattenPattern.js +55 -0
  93. package/dist/types/Entrypoint.d.ts +13 -7
  94. package/dist/types/adapter/commander/CommanderCLIEntrypoint.d.ts +3 -2
  95. package/dist/types/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +2 -1
  96. package/dist/types/adapter/express/ExpressHTTPEntrypoint.d.ts +3 -2
  97. package/dist/types/adapter/express/Responders.d.ts +2 -1
  98. package/dist/types/adapter/express/StaticUI.d.ts +2 -1
  99. package/dist/types/adapter/fastify/FastifyHTTPEntrypoint.d.ts +2 -1
  100. package/dist/types/adapter/fastify/Responders.d.ts +2 -1
  101. package/dist/types/adapter/http/HTTPServiceEntrypoint.d.ts +4 -3
  102. package/dist/types/adapter/http/HTTPServiceProxy.d.ts +190 -0
  103. package/dist/types/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +11 -7
  104. package/dist/types/adapter/schedule/ScheduleEntrypoint.d.ts +2 -1
  105. package/dist/types/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +2 -1
  106. package/dist/types/channel/EntrypointAdapter.d.ts +2 -2
  107. package/dist/types/decorators/HTTPAction.d.ts +5 -5
  108. package/dist/types/decorators/Schedule.d.ts +4 -2
  109. package/dist/types/decorators/ServiceAction.d.ts +12 -8
  110. package/dist/types/decorators/http/DELETE.d.ts +5 -5
  111. package/dist/types/decorators/http/GET.d.ts +7 -7
  112. package/dist/types/decorators/http/HEAD.d.ts +9 -9
  113. package/dist/types/decorators/http/OPTIONS.d.ts +8 -7
  114. package/dist/types/decorators/http/PATCH.d.ts +5 -5
  115. package/dist/types/decorators/http/POST.d.ts +5 -5
  116. package/dist/types/decorators/http/PUT.d.ts +7 -7
  117. package/dist/types/exceptions/AccessDeniedException.d.ts +7 -1
  118. package/dist/types/exceptions/EntrypointStoppedException.d.ts +2 -1
  119. package/dist/types/exceptions/InvalidActionGroupException.d.ts +4 -0
  120. package/dist/types/exceptions/ServiceUnavailableException.d.ts +15 -0
  121. package/dist/types/exports/Entrypoint.d.ts +3 -0
  122. package/dist/types/lib/AccessControl.d.ts +2 -1
  123. package/dist/types/lib/AccessControlRule.d.ts +2 -1
  124. package/dist/types/lib/ExplicitStatus.d.ts +11 -0
  125. package/dist/types/lib/Middleware.d.ts +2 -1
  126. package/dist/types/lib/Preflight.d.ts +8 -0
  127. package/dist/types/lib/ReadBody.d.ts +9 -0
  128. package/dist/types/lib/pattern/FlattenPattern.d.ts +14 -0
  129. package/package.json +35 -4
@@ -15,8 +15,9 @@ import { ServiceContext } from '../context/ServiceContext.js';
15
15
  * payload: null}`, `error` holding its properties (`errno`, `errMsg`, `statusCode`, `message`…); JSON-RPC answers it as
16
16
  * an error response. A message no pattern matches fails with `ControllerActionNotFoundException`.
17
17
  * @param pattern The pattern of the action: an object (nested 2 levels at most) whose keys the messages must hold with
18
- * the same values; a string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern
19
- * matching a message wins. The controller's `@Prefix({pattern})` is merged into it.
18
+ * the same values, the keys of a nested object too (`{res: {name: 'user'}}` does not match `{res: {name: 'order'}}`); a
19
+ * string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern matching a message
20
+ * wins. The controller's `@Prefix({pattern})` is merged into it.
20
21
  * @returns The method decorator.
21
22
  * @throws {InvalidActionPatternDepthException} When the class is declared, if the pattern is nested more than 2 levels.
22
23
  * @example
@@ -71,8 +72,9 @@ export declare function ServiceAction<ClassPrototype extends Controller, Method>
71
72
  * returned is sent back as `{success: true, error: null, payload}`, an error as `{success: false, error, payload:
72
73
  * null}` (a JSON-RPC result or error response).
73
74
  * @param pattern The pattern of the action: an object (nested 2 levels at most) whose keys the messages must hold with
74
- * the same values; a string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern
75
- * matching a message wins. The controller's `@Prefix({pattern})` is merged into it.
75
+ * the same values, the keys of a nested object too (`{res: {name: 'user'}}` does not match `{res: {name: 'order'}}`); a
76
+ * string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern matching a message
77
+ * wins. The controller's `@Prefix({pattern})` is merged into it.
76
78
  * @param dtoConstructor The DTO class validating the input: the message without the keys of the pattern.
77
79
  * @returns The method decorator.
78
80
  * @throws {InvalidActionPatternDepthException} When the class is declared, if the pattern is nested more than 2 levels.
@@ -83,8 +85,9 @@ export declare function ServiceAction<ClassPrototype extends Controller, Method,
83
85
  * without the keys of the pattern, is accepted as it is. The value returned is sent back as `{success: true, error:
84
86
  * null, payload}`, an error as `{success: false, error, payload: null}` (a JSON-RPC result or error response).
85
87
  * @param pattern The pattern of the action: an object (nested 2 levels at most) whose keys the messages must hold with
86
- * the same values; a string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern
87
- * matching a message wins. The controller's `@Prefix({pattern})` is merged into it.
88
+ * the same values, the keys of a nested object too (`{res: {name: 'user'}}` does not match `{res: {name: 'order'}}`); a
89
+ * string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern matching a message
90
+ * wins. The controller's `@Prefix({pattern})` is merged into it.
88
91
  * @param actionOptions The action options: `acl` runs the access control rules (false by default); `name` (unique in
89
92
  * the service actions, `ClassName:method` by default), `description` and `groups` describe the action; `rule` is an
90
93
  * access rule of the action; `middlewares` run before the ones `@UseMiddlewares` adds to the method.
@@ -101,8 +104,9 @@ export declare function ServiceAction<ClassPrototype extends Controller, Method>
101
104
  * plain object. The value returned is sent back as `{success: true, error: null, payload}`, an error as `{success:
102
105
  * false, error, payload: null}` (a JSON-RPC result or error response).
103
106
  * @param pattern The pattern of the action: an object (nested 2 levels at most) whose keys the messages must hold with
104
- * the same values; a string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern
105
- * matching a message wins. The controller's `@Prefix({pattern})` is merged into it.
107
+ * the same values, the keys of a nested object too (`{res: {name: 'user'}}` does not match `{res: {name: 'order'}}`); a
108
+ * string value may be a glob (`'user.*'`, `*` any characters, `?` one). The most specific pattern matching a message
109
+ * wins. The controller's `@Prefix({pattern})` is merged into it.
106
110
  * @param dtoConstructor The DTO class validating the input: the message without the keys of the pattern.
107
111
  * @param actionOptions The action options: `acl` runs the access control rules (false by default); `name` (unique in
108
112
  * the service actions, `ClassName:method` by default), `description` and `groups` describe the action; `rule` is an
@@ -5,11 +5,11 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP DELETE action on a route, to delete a resource: the shorthand of
7
7
  * `@HTTPAction(route, 'delete', …)`. The adapter assembles the input: by default, the query string merged with the
8
- * parsed body (JSON or URL encoded), then the route parameters over them. The middlewares run, the input is validated
9
- * against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is), the access
10
- * control runs when `acl` is set, then the method receives the validated input as a plain object. The query values and
11
- * the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The value
12
- * returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
8
+ * parsed body (JSON; URL encoded with Express), then the route parameters over them. The middlewares run, the input is
9
+ * validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is),
10
+ * the access control runs when `acl` is set, then the method receives the validated input as a plain object. The query
11
+ * values and the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The
12
+ * value returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
13
13
  * `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx
14
14
  * `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
15
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
@@ -5,13 +5,13 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP GET action on a route, to read a resource: the shorthand of
7
7
  * `@HTTPAction(route, 'get', …)`. The adapter assembles the input: by default, the query string merged with the parsed
8
- * body (JSON or URL encoded), then the route parameters over them. The middlewares run, the input is validated against
9
- * the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is), the access control
10
- * runs when `acl` is set, then the method receives the validated input as a plain object. The query values and the
11
- * route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The value returned
12
- * is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`; `Result.status()`
13
- * sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx `statusCode` along its
14
- * causes (400 for an invalid input), else its own `statusCode`, else 500.
8
+ * body (JSON; URL encoded with Express), then the route parameters over them. The middlewares run, the input is
9
+ * validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is),
10
+ * the access control runs when `acl` is set, then the method receives the validated input as a plain object. The query
11
+ * values and the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The
12
+ * value returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
13
+ * `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx
14
+ * `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
15
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
16
16
  * prepended to it.
17
17
  * @returns The method decorator.
@@ -5,14 +5,14 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP HEAD action on a route, to answer the headers of a resource without its body:
7
7
  * the shorthand of `@HTTPAction(route, 'head', …)`. The adapter assembles the input: by default, the query string
8
- * merged with the parsed body (JSON or URL encoded), then the route parameters over them. The middlewares run, the
9
- * input is validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as
10
- * it is), the access control runs when `acl` is set, then the method receives the validated input as a plain object.
11
- * The query values and the route parameters are strings and the DTO schemas are strict: convert them with
8
+ * merged with the parsed body (JSON; URL encoded with Express), then the route parameters over them. The middlewares
9
+ * run, the input is validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is
10
+ * accepted as it is), the access control runs when `acl` is set, then the method receives the validated input as a
11
+ * plain object. The query values and the route parameters are strings and the DTO schemas are strict: convert them with
12
12
  * `.strict(false)`. The value returned is answered by the adapter's responder: as JSON by default, with the status 204
13
13
  * for `undefined`; `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with
14
- * the first 4xx `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
- * With Fastify, a GET action also answers the HEAD requests of its route unless the route has a HEAD action.
14
+ * the first 4xx `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500. A GET
15
+ * action also answers the HEAD requests of its route, unless the route has a HEAD action.
16
16
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
17
17
  * prepended to it.
18
18
  * @returns The method decorator.
@@ -37,7 +37,7 @@ export declare function HEAD<ClassPrototype extends Controller, Method>(r: strin
37
37
  * over them (the default of the adapters); the method receives it validated, as a plain object. The value returned is
38
38
  * answered as JSON (204 for `undefined`), an error as `{errno, errMsg}` with its status (400 for an invalid input, else
39
39
  * 500 by default).
40
- * With Fastify, a GET action also answers the HEAD requests of its route unless the route has a HEAD action.
40
+ * A GET action also answers the HEAD requests of its route, unless the route has a HEAD action.
41
41
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
42
42
  * prepended to it.
43
43
  * @param dtoConstructor The DTO class validating the input; the query values and the route parameters are strings,
@@ -50,7 +50,7 @@ export declare function HEAD<ClassPrototype extends Controller, Method, DTOConst
50
50
  * `@HTTPAction(route, 'head', …)`. The input is the query string merged with the parsed body, then the route parameters
51
51
  * over them (the default of the adapters), accepted as it is. The value returned is answered as JSON (204 for
52
52
  * `undefined`), an error as `{errno, errMsg}` with its status (500 by default).
53
- * With Fastify, a GET action also answers the HEAD requests of its route unless the route has a HEAD action.
53
+ * A GET action also answers the HEAD requests of its route, unless the route has a HEAD action.
54
54
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
55
55
  * prepended to it.
56
56
  * @param actionOptions The action options: `acl` runs the access control rules (false by default); `name` (unique in the
@@ -68,7 +68,7 @@ export declare function HEAD<ClassPrototype extends Controller, Method>(r: strin
68
68
  * then the route parameters over them (the default of the adapters); the method receives it validated, as a plain
69
69
  * object. The value returned is answered as JSON (204 for `undefined`), an error as `{errno, errMsg}` with its status
70
70
  * (400 for an invalid input, else 500 by default).
71
- * With Fastify, a GET action also answers the HEAD requests of its route unless the route has a HEAD action.
71
+ * A GET action also answers the HEAD requests of its route, unless the route has a HEAD action.
72
72
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
73
73
  * prepended to it.
74
74
  * @param dtoConstructor The DTO class validating the input; the query values and the route parameters are strings,
@@ -5,13 +5,14 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP OPTIONS action on a route, to describe the communication options of a
7
7
  * resource: the shorthand of `@HTTPAction(route, 'options', …)`. The adapter assembles the input: by default, the query
8
- * string merged with the parsed body (JSON or URL encoded), then the route parameters over them. The middlewares run,
9
- * the input is validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted
10
- * as it is), the access control runs when `acl` is set, then the method receives the validated input as a plain object.
11
- * The query values and the route parameters are strings and the DTO schemas are strict: convert them with
12
- * `.strict(false)`. The value returned is answered by the adapter's responder: as JSON by default, with the status 204
13
- * for `undefined`; `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with
14
- * the first 4xx `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
8
+ * string merged with the parsed body (JSON; URL encoded with Express), then the route parameters over them. The
9
+ * middlewares run, the input is validated against the DTO (the defaults applied, the unknown keys removed; without a
10
+ * DTO, it is accepted as it is), the access control runs when `acl` is set, then the method receives the validated
11
+ * input as a plain object. The query values and the route parameters are strings and the DTO schemas are strict:
12
+ * convert them with `.strict(false)`. The value returned is answered by the adapter's responder: as JSON by default,
13
+ * with the status 204 for `undefined`; `Result.status()` sets a status and headers. An error thrown is answered as
14
+ * `{errno, errMsg}` with the first 4xx `statusCode` along its causes (400 for an invalid input), else its own
15
+ * `statusCode`, else 500.
15
16
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
16
17
  * prepended to it.
17
18
  * @returns The method decorator.
@@ -5,11 +5,11 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP PATCH action on a route, to update a part of a resource: the shorthand of
7
7
  * `@HTTPAction(route, 'patch', …)`. The adapter assembles the input: by default, the query string merged with the
8
- * parsed body (JSON or URL encoded), then the route parameters over them. The middlewares run, the input is validated
9
- * against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is), the access
10
- * control runs when `acl` is set, then the method receives the validated input as a plain object. The query values and
11
- * the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The value
12
- * returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
8
+ * parsed body (JSON; URL encoded with Express), then the route parameters over them. The middlewares run, the input is
9
+ * validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is),
10
+ * the access control runs when `acl` is set, then the method receives the validated input as a plain object. The query
11
+ * values and the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The
12
+ * value returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
13
13
  * `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx
14
14
  * `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
15
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
@@ -5,11 +5,11 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP POST action on a route, to create a resource or run a command: the shorthand
7
7
  * of `@HTTPAction(route, 'post', …)`. The adapter assembles the input: by default, the query string merged with the
8
- * parsed body (JSON or URL encoded), then the route parameters over them. The middlewares run, the input is validated
9
- * against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is), the access
10
- * control runs when `acl` is set, then the method receives the validated input as a plain object. The query values and
11
- * the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The value
12
- * returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
8
+ * parsed body (JSON; URL encoded with Express), then the route parameters over them. The middlewares run, the input is
9
+ * validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is),
10
+ * the access control runs when `acl` is set, then the method receives the validated input as a plain object. The query
11
+ * values and the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The
12
+ * value returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
13
13
  * `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx
14
14
  * `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
15
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
@@ -5,13 +5,13 @@ import { HTTPContext } from '../../context/HTTPContext.js';
5
5
  /**
6
6
  * Expose the controller method as an HTTP PUT action on a route, to replace a resource: the shorthand of
7
7
  * `@HTTPAction(route, 'put', …)`. The adapter assembles the input: by default, the query string merged with the parsed
8
- * body (JSON or URL encoded), then the route parameters over them. The middlewares run, the input is validated against
9
- * the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is), the access control
10
- * runs when `acl` is set, then the method receives the validated input as a plain object. The query values and the
11
- * route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The value returned
12
- * is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`; `Result.status()`
13
- * sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx `statusCode` along its
14
- * causes (400 for an invalid input), else its own `statusCode`, else 500.
8
+ * body (JSON; URL encoded with Express), then the route parameters over them. The middlewares run, the input is
9
+ * validated against the DTO (the defaults applied, the unknown keys removed; without a DTO, it is accepted as it is),
10
+ * the access control runs when `acl` is set, then the method receives the validated input as a plain object. The query
11
+ * values and the route parameters are strings and the DTO schemas are strict: convert them with `.strict(false)`. The
12
+ * value returned is answered by the adapter's responder: as JSON by default, with the status 204 for `undefined`;
13
+ * `Result.status()` sets a status and headers. An error thrown is answered as `{errno, errMsg}` with the first 4xx
14
+ * `statusCode` along its causes (400 for an invalid input), else its own `statusCode`, else 500.
15
15
  * @param r The route, in the syntax of the HTTP adapter (`/users/:id`); the controller's `@Prefix({route})` is
16
16
  * prepended to it.
17
17
  * @returns The method decorator.
@@ -5,6 +5,12 @@ import { Exception } from '@lakutata/core';
5
5
  */
6
6
  export declare class AccessDeniedException extends Exception {
7
7
  errno: string | number;
8
- message: string;
9
8
  readonly statusCode: number;
9
+ /**
10
+ * Create the exception: its message is "Access denied" unless one is given.
11
+ * @param template The message, or a template filled from the parameters (see `Exception`), or an error whose
12
+ * message it takes; "Access denied" by default.
13
+ * @param params The parameters of the template.
14
+ */
15
+ constructor(template?: string | Error, ...params: any[]);
10
16
  }
@@ -7,10 +7,15 @@ const core_1 = require("@lakutata/core");
7
7
  * Its errno is `E_ACCESS_DENY`, its HTTP status 403.
8
8
  */
9
9
  class AccessDeniedException extends core_1.Exception {
10
- constructor() {
11
- super(...arguments);
10
+ /**
11
+ * Create the exception: its message is "Access denied" unless one is given.
12
+ * @param template The message, or a template filled from the parameters (see `Exception`), or an error whose
13
+ * message it takes; "Access denied" by default.
14
+ * @param params The parameters of the template.
15
+ */
16
+ constructor(template, ...params) {
17
+ super((template ?? 'Access denied'), ...params);
12
18
  this.errno = 'E_ACCESS_DENY';
13
- this.message = 'Access denied';
14
19
  this.statusCode = 403;
15
20
  }
16
21
  }
@@ -1,7 +1,8 @@
1
1
  import { Exception } from '@lakutata/core';
2
2
  /**
3
3
  * The request arrived while the entrypoint is stopping (the application exiting): it is refused, the requests in
4
- * progress being waited for. Its errno is `E_ENTRYPOINT_STOPPED`, its HTTP status 503.
4
+ * progress being waited for. A request still running when the entrypoint's `shutdownTimeout` runs out is aborted with
5
+ * it too. Its errno is `E_ENTRYPOINT_STOPPED`, its HTTP status 503.
5
6
  */
6
7
  export declare class EntrypointStoppedException extends Exception {
7
8
  errno: string | number;
@@ -4,7 +4,8 @@ exports.EntrypointStoppedException = void 0;
4
4
  const core_1 = require("@lakutata/core");
5
5
  /**
6
6
  * The request arrived while the entrypoint is stopping (the application exiting): it is refused, the requests in
7
- * progress being waited for. Its errno is `E_ENTRYPOINT_STOPPED`, its HTTP status 503.
7
+ * progress being waited for. A request still running when the entrypoint's `shutdownTimeout` runs out is aborted with
8
+ * it too. Its errno is `E_ENTRYPOINT_STOPPED`, its HTTP status 503.
8
9
  */
9
10
  class EntrypointStoppedException extends core_1.Exception {
10
11
  constructor() {
@@ -1,4 +1,8 @@
1
1
  import { Exception } from '@lakutata/core';
2
+ /**
3
+ * An action is in a group that the `*ActionGroups` option of its channel (`httpActionGroups`, `cliActionGroups`,
4
+ * `serviceActionGroups`) does not declare, when the entrypoint initializes. Its errno is `E_INVALID_ACTION_GROUP`.
5
+ */
2
6
  export declare class InvalidActionGroupException extends Exception {
3
7
  errno: string | number;
4
8
  }
@@ -2,6 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InvalidActionGroupException = void 0;
4
4
  const core_1 = require("@lakutata/core");
5
+ /**
6
+ * An action is in a group that the `*ActionGroups` option of its channel (`httpActionGroups`, `cliActionGroups`,
7
+ * `serviceActionGroups`) does not declare, when the entrypoint initializes. Its errno is `E_INVALID_ACTION_GROUP`.
8
+ */
5
9
  class InvalidActionGroupException extends core_1.Exception {
6
10
  constructor() {
7
11
  super(...arguments);
@@ -0,0 +1,15 @@
1
+ import { Exception } from '@lakutata/core';
2
+ /**
3
+ * A service called by an `HTTPServiceProxy` gave no response: it could not be reached, it did not answer in time, or
4
+ * its answer was not a service response (the error page of a proxy in front of it…). Its `cause` is the error of the
5
+ * request when there is one, its `service` the address of the service. Its errno is `E_SERVICE_UNAVAILABLE`, its HTTP
6
+ * status 503. The failures of the actions themselves are thrown as `ServiceInvokeException`.
7
+ */
8
+ export declare class ServiceUnavailableException extends Exception {
9
+ errno: string | number;
10
+ readonly statusCode: number;
11
+ /**
12
+ * The address of the service called.
13
+ */
14
+ service?: string;
15
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceUnavailableException = void 0;
4
+ const core_1 = require("@lakutata/core");
5
+ /**
6
+ * A service called by an `HTTPServiceProxy` gave no response: it could not be reached, it did not answer in time, or
7
+ * its answer was not a service response (the error page of a proxy in front of it…). Its `cause` is the error of the
8
+ * request when there is one, its `service` the address of the service. Its errno is `E_SERVICE_UNAVAILABLE`, its HTTP
9
+ * status 503. The failures of the actions themselves are thrown as `ServiceInvokeException`.
10
+ */
11
+ class ServiceUnavailableException extends core_1.Exception {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.errno = 'E_SERVICE_UNAVAILABLE';
15
+ this.statusCode = 503;
16
+ }
17
+ }
18
+ exports.ServiceUnavailableException = ServiceUnavailableException;
@@ -3,6 +3,7 @@ export * from '../lib/Controller.js';
3
3
  export * from '../lib/AccessControlRule.js';
4
4
  export * from '../exceptions/AccessDeniedException.js';
5
5
  export * from '../exceptions/DuplicateActionNameException.js';
6
+ export * from '../exceptions/InvalidActionGroupException.js';
6
7
  export * from '../exceptions/ControllerActionNotFoundException.js';
7
8
  export { AccessControl } from '../lib/AccessControl.js';
8
9
  export { Middleware, type ActionInvocation, type Next, type MiddlewareHandler, type MiddlewareDefinition } from '../lib/Middleware.js';
@@ -21,4 +22,6 @@ export * from '../exceptions/EntrypointStoppedException.js';
21
22
  export * from '../exceptions/ServiceInvokeException.js';
22
23
  export { scheduleEntrypoint, type ScheduleEntrypointOptions } from '../adapter/schedule/ScheduleEntrypoint.js';
23
24
  export { httpServiceEntrypoint, httpRequestOfContext, type HTTPServiceEntrypointOptions } from '../adapter/http/HTTPServiceEntrypoint.js';
25
+ export { buildHTTPServiceProxy, HTTPServiceProxy, type BuildHTTPServiceProxyOptions } from '../adapter/http/HTTPServiceProxy.js';
26
+ export * from '../exceptions/ServiceUnavailableException.js';
24
27
  export { Cron, parseDuration } from '../lib/schedule/Cron.js';
@@ -14,12 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.parseDuration = exports.Cron = exports.httpRequestOfContext = exports.httpServiceEntrypoint = exports.scheduleEntrypoint = exports.EventsResult = exports.FileResult = exports.StatusResult = exports.Result = exports.ActionResult = exports.PrefixOptions = exports.Middleware = exports.AccessControl = void 0;
17
+ exports.parseDuration = exports.Cron = exports.HTTPServiceProxy = exports.buildHTTPServiceProxy = exports.httpRequestOfContext = exports.httpServiceEntrypoint = exports.scheduleEntrypoint = exports.EventsResult = exports.FileResult = exports.StatusResult = exports.Result = exports.ActionResult = exports.PrefixOptions = exports.Middleware = exports.AccessControl = void 0;
18
18
  __exportStar(require("../Entrypoint.js"), exports);
19
19
  __exportStar(require("../lib/Controller.js"), exports);
20
20
  __exportStar(require("../lib/AccessControlRule.js"), exports);
21
21
  __exportStar(require("../exceptions/AccessDeniedException.js"), exports);
22
22
  __exportStar(require("../exceptions/DuplicateActionNameException.js"), exports);
23
+ __exportStar(require("../exceptions/InvalidActionGroupException.js"), exports);
23
24
  __exportStar(require("../exceptions/ControllerActionNotFoundException.js"), exports);
24
25
  var AccessControl_js_1 = require("../lib/AccessControl.js");
25
26
  Object.defineProperty(exports, "AccessControl", { enumerable: true, get: function () { return AccessControl_js_1.AccessControl; } });
@@ -47,6 +48,10 @@ Object.defineProperty(exports, "scheduleEntrypoint", { enumerable: true, get: fu
47
48
  var HTTPServiceEntrypoint_js_1 = require("../adapter/http/HTTPServiceEntrypoint.js");
48
49
  Object.defineProperty(exports, "httpServiceEntrypoint", { enumerable: true, get: function () { return HTTPServiceEntrypoint_js_1.httpServiceEntrypoint; } });
49
50
  Object.defineProperty(exports, "httpRequestOfContext", { enumerable: true, get: function () { return HTTPServiceEntrypoint_js_1.httpRequestOfContext; } });
51
+ var HTTPServiceProxy_js_1 = require("../adapter/http/HTTPServiceProxy.js");
52
+ Object.defineProperty(exports, "buildHTTPServiceProxy", { enumerable: true, get: function () { return HTTPServiceProxy_js_1.buildHTTPServiceProxy; } });
53
+ Object.defineProperty(exports, "HTTPServiceProxy", { enumerable: true, get: function () { return HTTPServiceProxy_js_1.HTTPServiceProxy; } });
54
+ __exportStar(require("../exceptions/ServiceUnavailableException.js"), exports);
50
55
  var Cron_js_1 = require("../lib/schedule/Cron.js");
51
56
  Object.defineProperty(exports, "Cron", { enumerable: true, get: function () { return Cron_js_1.Cron; } });
52
57
  Object.defineProperty(exports, "parseDuration", { enumerable: true, get: function () { return Cron_js_1.parseDuration; } });
@@ -39,7 +39,8 @@ import { AccessControlRule, AccessControlRuleHandler } from './AccessControlRule
39
39
  * name: 'Report',
40
40
  * components: {
41
41
  * entrypoint: {class: AuditedEntrypoint, controllers: [ReportController]}
42
- * }
42
+ * },
43
+ * bootstrap: ['entrypoint']
43
44
  * }))
44
45
  * ```
45
46
  */
@@ -52,7 +52,8 @@ const utils_1 = require("@lakutata/utils");
52
52
  * name: 'Report',
53
53
  * components: {
54
54
  * entrypoint: {class: AuditedEntrypoint, controllers: [ReportController]}
55
- * }
55
+ * },
56
+ * bootstrap: ['entrypoint']
56
57
  * }))
57
58
  * ```
58
59
  */
@@ -49,7 +49,8 @@ export type AccessControlRuleHandler<T extends BaseContext<Record<string, any>>>
49
49
  * rules: [AdminRule],
50
50
  * httpActionGroups: {admin: 'Administration'}
51
51
  * })
52
- * }
52
+ * },
53
+ * bootstrap: ['entrypoint']
53
54
  * }))
54
55
  * ```
55
56
  */
@@ -51,7 +51,8 @@ const di_1 = require("@lakutata/core/decorator/di");
51
51
  * rules: [AdminRule],
52
52
  * httpActionGroups: {admin: 'Administration'}
53
53
  * })
54
- * }
54
+ * },
55
+ * bootstrap: ['entrypoint']
55
56
  * }))
56
57
  * ```
57
58
  */
@@ -0,0 +1,11 @@
1
+ import type { ServerResponse } from 'node:http';
2
+ /**
3
+ * Mark the status of a response as set by the action
4
+ * @param response
5
+ */
6
+ export declare function markExplicitStatus(response: ServerResponse): void;
7
+ /**
8
+ * Whether the status of a response was set by the action
9
+ * @param response
10
+ */
11
+ export declare function hasExplicitStatus(response: ServerResponse): boolean;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.markExplicitStatus = markExplicitStatus;
4
+ exports.hasExplicitStatus = hasExplicitStatus;
5
+ /**
6
+ * The responses whose status was set by the action (a StatusResult): the default responders keep it, 200 included
7
+ */
8
+ const explicitStatuses = new WeakSet();
9
+ /**
10
+ * Mark the status of a response as set by the action
11
+ * @param response
12
+ */
13
+ function markExplicitStatus(response) {
14
+ explicitStatuses.add(response);
15
+ }
16
+ /**
17
+ * Whether the status of a response was set by the action
18
+ * @param response
19
+ */
20
+ function hasExplicitStatus(response) {
21
+ return explicitStatuses.has(response);
22
+ }
@@ -89,7 +89,8 @@ export type MiddlewareHandler = (invocation: ActionInvocation, next: Next) => Pr
89
89
  * controllers: [StatusController],
90
90
  * middlewares: [Timing]
91
91
  * })
92
- * }
92
+ * },
93
+ * bootstrap: ['entrypoint']
93
94
  * }))
94
95
  * ```
95
96
  */
@@ -55,7 +55,8 @@ const MiddlewareNextCalledException_js_1 = require("../exceptions/MiddlewareNext
55
55
  * controllers: [StatusController],
56
56
  * middlewares: [Timing]
57
57
  * })
58
- * }
58
+ * },
59
+ * bootstrap: ['entrypoint']
59
60
  * }))
60
61
  * ```
61
62
  */
@@ -0,0 +1,8 @@
1
+ import type { IncomingMessage, OutgoingHttpHeaders } from 'node:http';
2
+ /**
3
+ * The headers of the answer to a preflight of a browser: the headers the request asks for are allowed (Authorization,
4
+ * the headers of the application…), the headers of the adapter when it asks for none
5
+ * @param request
6
+ * @param headers the CORS headers of the adapter
7
+ */
8
+ export declare function preflightHeaders(request: IncomingMessage, headers: OutgoingHttpHeaders): OutgoingHttpHeaders;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preflightHeaders = preflightHeaders;
4
+ /**
5
+ * The headers of the answer to a preflight of a browser: the headers the request asks for are allowed (Authorization,
6
+ * the headers of the application…), the headers of the adapter when it asks for none
7
+ * @param request
8
+ * @param headers the CORS headers of the adapter
9
+ */
10
+ function preflightHeaders(request, headers) {
11
+ const requested = request.headers['access-control-request-headers'];
12
+ return { ...headers, 'Access-Control-Allow-Headers': requested || headers['Access-Control-Allow-Headers'], 'Vary': 'Access-Control-Request-Headers' };
13
+ }
@@ -0,0 +1,9 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ /**
3
+ * Read the body of a request, up to a limit. Over the limit, it fails with a 413 error at once, and the rest of the body
4
+ * is read and dropped: the connection stays usable for the next request of the client (closing it while the client
5
+ * still sends would fail its request, keeping it unread would fail the next one)
6
+ * @param request
7
+ * @param limit bytes
8
+ */
9
+ export declare function readBody(request: IncomingMessage, limit: number): Promise<string>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readBody = readBody;
4
+ /**
5
+ * Read the body of a request, up to a limit. Over the limit, it fails with a 413 error at once, and the rest of the body
6
+ * is read and dropped: the connection stays usable for the next request of the client (closing it while the client
7
+ * still sends would fail its request, keeping it unread would fail the next one)
8
+ * @param request
9
+ * @param limit bytes
10
+ */
11
+ function readBody(request, limit) {
12
+ return new Promise((resolve, reject) => {
13
+ const chunks = [];
14
+ let size = 0;
15
+ const end = () => resolve(Buffer.concat(chunks).toString('utf8'));
16
+ const collect = (chunk) => {
17
+ size += chunk.length;
18
+ if (size <= limit)
19
+ return void chunks.push(chunk);
20
+ request.off('data', collect).off('end', end).on('data', () => undefined);
21
+ reject(Object.assign(new Error(`The body of the request is larger than ${limit} bytes`), { statusCode: 413 }));
22
+ };
23
+ request.on('data', collect).once('end', end).once('error', reject);
24
+ });
25
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A pattern with the properties of its nested objects as keys joined by dots (`{res: {name: 'user'}}` gives
3
+ * `{'res.name': 'user'}`): their values are compared one by one, not as the text of their object. An empty nested
4
+ * object stays a value.
5
+ * @param pattern
6
+ * @param prefix
7
+ */
8
+ export declare function flattenPattern(pattern: Record<string, any>, prefix?: string): Record<string, any>;
9
+ /**
10
+ * A subject matched by the flattened patterns: its own properties, with the ones of its nested objects as keys joined
11
+ * by dots
12
+ * @param subject
13
+ */
14
+ export declare function flattenSubject(subject: Record<string, any>): Record<string, any>;