@furystack/rest-service 12.3.5 → 14.0.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 (252) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +47 -28
  3. package/esm/actions/get-current-user.spec.js +10 -6
  4. package/esm/actions/get-current-user.spec.js.map +1 -1
  5. package/esm/actions/index.d.ts +0 -1
  6. package/esm/actions/index.d.ts.map +1 -1
  7. package/esm/actions/index.js +0 -1
  8. package/esm/actions/index.js.map +1 -1
  9. package/esm/actions/is-authenticated.spec.js +10 -6
  10. package/esm/actions/is-authenticated.spec.js.map +1 -1
  11. package/esm/actions/logout-action.spec.js +11 -9
  12. package/esm/actions/logout-action.spec.js.map +1 -1
  13. package/esm/actions/logout.js +1 -1
  14. package/esm/actions/logout.js.map +1 -1
  15. package/esm/actions/password-login-action.js +1 -1
  16. package/esm/actions/password-login-action.js.map +1 -1
  17. package/esm/actions/password-login-action.spec.js +23 -28
  18. package/esm/actions/password-login-action.spec.js.map +1 -1
  19. package/esm/authenticate.js +1 -1
  20. package/esm/authenticate.js.map +1 -1
  21. package/esm/authenticate.spec.js +41 -33
  22. package/esm/authenticate.spec.js.map +1 -1
  23. package/esm/authorize.spec.js +34 -29
  24. package/esm/authorize.spec.js.map +1 -1
  25. package/esm/endpoint-generators/create-delete-endpoint.d.ts +6 -11
  26. package/esm/endpoint-generators/create-delete-endpoint.d.ts.map +1 -1
  27. package/esm/endpoint-generators/create-delete-endpoint.js +7 -11
  28. package/esm/endpoint-generators/create-delete-endpoint.js.map +1 -1
  29. package/esm/endpoint-generators/create-delete-endpoint.spec.js +14 -21
  30. package/esm/endpoint-generators/create-delete-endpoint.spec.js.map +1 -1
  31. package/esm/endpoint-generators/create-get-collection-endpoint.d.ts +11 -11
  32. package/esm/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -1
  33. package/esm/endpoint-generators/create-get-collection-endpoint.js +13 -12
  34. package/esm/endpoint-generators/create-get-collection-endpoint.js.map +1 -1
  35. package/esm/endpoint-generators/create-get-collection-endpoint.spec.js +43 -70
  36. package/esm/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -1
  37. package/esm/endpoint-generators/create-get-entity-endpoint.d.ts +6 -11
  38. package/esm/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -1
  39. package/esm/endpoint-generators/create-get-entity-endpoint.js +7 -11
  40. package/esm/endpoint-generators/create-get-entity-endpoint.js.map +1 -1
  41. package/esm/endpoint-generators/create-get-entity-endpoint.spec.js +16 -33
  42. package/esm/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -1
  43. package/esm/endpoint-generators/create-get-openapi-document-action.d.ts +1 -15
  44. package/esm/endpoint-generators/create-get-openapi-document-action.d.ts.map +1 -1
  45. package/esm/endpoint-generators/create-get-openapi-document-action.js +1 -24
  46. package/esm/endpoint-generators/create-get-openapi-document-action.js.map +1 -1
  47. package/esm/endpoint-generators/create-get-schema-action.d.ts +1 -1
  48. package/esm/endpoint-generators/create-get-schema-action.d.ts.map +1 -1
  49. package/esm/endpoint-generators/create-get-schema-action.js.map +1 -1
  50. package/esm/endpoint-generators/create-patch-endpoint.d.ts +7 -13
  51. package/esm/endpoint-generators/create-patch-endpoint.d.ts.map +1 -1
  52. package/esm/endpoint-generators/create-patch-endpoint.js +8 -13
  53. package/esm/endpoint-generators/create-patch-endpoint.js.map +1 -1
  54. package/esm/endpoint-generators/create-patch-endpoint.spec.js +10 -17
  55. package/esm/endpoint-generators/create-patch-endpoint.spec.js.map +1 -1
  56. package/esm/endpoint-generators/create-post-endpoint.d.ts +7 -13
  57. package/esm/endpoint-generators/create-post-endpoint.d.ts.map +1 -1
  58. package/esm/endpoint-generators/create-post-endpoint.js +8 -13
  59. package/esm/endpoint-generators/create-post-endpoint.js.map +1 -1
  60. package/esm/endpoint-generators/create-post-endpoint.spec.js +41 -14
  61. package/esm/endpoint-generators/create-post-endpoint.spec.js.map +1 -1
  62. package/esm/endpoint-generators/utils.d.ts +17 -2
  63. package/esm/endpoint-generators/utils.d.ts.map +1 -1
  64. package/esm/endpoint-generators/utils.js +33 -20
  65. package/esm/endpoint-generators/utils.js.map +1 -1
  66. package/esm/endpoint-generators/with-schema-and-openapi-action.d.ts +0 -2
  67. package/esm/endpoint-generators/with-schema-and-openapi-action.d.ts.map +1 -1
  68. package/esm/get-schema-from-api.d.ts +1 -1
  69. package/esm/get-schema-from-api.d.ts.map +1 -1
  70. package/esm/get-schema-from-api.spec.js.map +1 -1
  71. package/esm/helpers.d.ts +53 -87
  72. package/esm/helpers.d.ts.map +1 -1
  73. package/esm/helpers.js +91 -92
  74. package/esm/helpers.js.map +1 -1
  75. package/esm/helpers.spec.d.ts +2 -1
  76. package/esm/helpers.spec.d.ts.map +1 -1
  77. package/esm/helpers.spec.js +41 -38
  78. package/esm/helpers.spec.js.map +1 -1
  79. package/esm/http-authentication-settings.d.ts +35 -12
  80. package/esm/http-authentication-settings.d.ts.map +1 -1
  81. package/esm/http-authentication-settings.js +21 -29
  82. package/esm/http-authentication-settings.js.map +1 -1
  83. package/esm/http-server-pool.d.ts +64 -0
  84. package/esm/http-server-pool.d.ts.map +1 -0
  85. package/esm/http-server-pool.js +95 -0
  86. package/esm/http-server-pool.js.map +1 -0
  87. package/esm/http-server-pool.spec.d.ts +2 -0
  88. package/esm/http-server-pool.spec.d.ts.map +1 -0
  89. package/esm/http-server-pool.spec.js +193 -0
  90. package/esm/http-server-pool.spec.js.map +1 -0
  91. package/esm/http-user-context.d.ts +31 -44
  92. package/esm/http-user-context.d.ts.map +1 -1
  93. package/esm/http-user-context.js +76 -95
  94. package/esm/http-user-context.js.map +1 -1
  95. package/esm/http-user-context.spec.d.ts +8 -2
  96. package/esm/http-user-context.spec.d.ts.map +1 -1
  97. package/esm/http-user-context.spec.js +189 -337
  98. package/esm/http-user-context.spec.js.map +1 -1
  99. package/esm/index.d.ts +6 -4
  100. package/esm/index.d.ts.map +1 -1
  101. package/esm/index.js +6 -4
  102. package/esm/index.js.map +1 -1
  103. package/esm/login-response-strategy.d.ts +11 -10
  104. package/esm/login-response-strategy.d.ts.map +1 -1
  105. package/esm/login-response-strategy.js +7 -6
  106. package/esm/login-response-strategy.js.map +1 -1
  107. package/esm/login-response-strategy.spec.js +25 -29
  108. package/esm/login-response-strategy.spec.js.map +1 -1
  109. package/esm/openapi/generate-openapi-document.d.ts +0 -8
  110. package/esm/openapi/generate-openapi-document.d.ts.map +1 -1
  111. package/esm/openapi/generate-openapi-document.js +0 -2
  112. package/esm/openapi/generate-openapi-document.js.map +1 -1
  113. package/esm/proxy-manager.spec.js +152 -176
  114. package/esm/proxy-manager.spec.js.map +1 -1
  115. package/esm/proxy-runtime.d.ts +27 -0
  116. package/esm/proxy-runtime.d.ts.map +1 -0
  117. package/esm/proxy-runtime.js +45 -0
  118. package/esm/proxy-runtime.js.map +1 -0
  119. package/esm/proxy-runtime.spec.d.ts +2 -0
  120. package/esm/proxy-runtime.spec.d.ts.map +1 -0
  121. package/esm/proxy-runtime.spec.js +39 -0
  122. package/esm/proxy-runtime.spec.js.map +1 -0
  123. package/esm/rest-api-runtime.d.ts +76 -0
  124. package/esm/rest-api-runtime.d.ts.map +1 -0
  125. package/esm/rest-api-runtime.js +131 -0
  126. package/esm/rest-api-runtime.js.map +1 -0
  127. package/esm/rest-api-runtime.spec.d.ts +2 -0
  128. package/esm/rest-api-runtime.spec.d.ts.map +1 -0
  129. package/esm/rest-api-runtime.spec.js +58 -0
  130. package/esm/rest-api-runtime.spec.js.map +1 -0
  131. package/esm/rest-service.integration.spec.d.ts +1 -1
  132. package/esm/rest-service.integration.spec.d.ts.map +1 -1
  133. package/esm/rest-service.integration.spec.js +60 -82
  134. package/esm/rest-service.integration.spec.js.map +1 -1
  135. package/esm/rest.integration.test.js +26 -84
  136. package/esm/rest.integration.test.js.map +1 -1
  137. package/esm/server-telemetry.d.ts +57 -0
  138. package/esm/server-telemetry.d.ts.map +1 -0
  139. package/esm/server-telemetry.js +26 -0
  140. package/esm/server-telemetry.js.map +1 -0
  141. package/esm/server-telemetry.spec.d.ts +2 -0
  142. package/esm/server-telemetry.spec.d.ts.map +1 -0
  143. package/esm/server-telemetry.spec.js +52 -0
  144. package/esm/server-telemetry.spec.js.map +1 -0
  145. package/esm/static-server-manager.spec.js +60 -125
  146. package/esm/static-server-manager.spec.js.map +1 -1
  147. package/esm/static-site-runtime.d.ts +21 -0
  148. package/esm/static-site-runtime.d.ts.map +1 -0
  149. package/esm/static-site-runtime.js +48 -0
  150. package/esm/static-site-runtime.js.map +1 -0
  151. package/esm/static-site-runtime.spec.d.ts +2 -0
  152. package/esm/static-site-runtime.spec.d.ts.map +1 -0
  153. package/esm/static-site-runtime.spec.js +30 -0
  154. package/esm/static-site-runtime.spec.js.map +1 -0
  155. package/esm/user-store.d.ts +39 -0
  156. package/esm/user-store.d.ts.map +1 -0
  157. package/esm/user-store.js +62 -0
  158. package/esm/user-store.js.map +1 -0
  159. package/esm/user-store.spec.d.ts +2 -0
  160. package/esm/user-store.spec.d.ts.map +1 -0
  161. package/esm/user-store.spec.js +72 -0
  162. package/esm/user-store.spec.js.map +1 -0
  163. package/esm/validate.integration.spec.js +26 -83
  164. package/esm/validate.integration.spec.js.map +1 -1
  165. package/package.json +8 -8
  166. package/src/actions/get-current-user.spec.ts +11 -10
  167. package/src/actions/index.ts +0 -1
  168. package/src/actions/is-authenticated.spec.ts +12 -7
  169. package/src/actions/logout-action.spec.ts +12 -12
  170. package/src/actions/logout.ts +1 -1
  171. package/src/actions/password-login-action.spec.ts +30 -30
  172. package/src/actions/password-login-action.ts +1 -1
  173. package/src/authenticate.spec.ts +45 -51
  174. package/src/authenticate.ts +1 -1
  175. package/src/authorize.spec.ts +37 -39
  176. package/src/endpoint-generators/create-delete-endpoint.spec.ts +16 -24
  177. package/src/endpoint-generators/create-delete-endpoint.ts +11 -17
  178. package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +45 -78
  179. package/src/endpoint-generators/create-get-collection-endpoint.ts +17 -19
  180. package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +17 -33
  181. package/src/endpoint-generators/create-get-entity-endpoint.ts +11 -17
  182. package/src/endpoint-generators/create-get-openapi-document-action.ts +2 -38
  183. package/src/endpoint-generators/create-get-schema-action.ts +1 -1
  184. package/src/endpoint-generators/create-patch-endpoint.spec.ts +11 -18
  185. package/src/endpoint-generators/create-patch-endpoint.ts +12 -23
  186. package/src/endpoint-generators/create-post-endpoint.spec.ts +45 -14
  187. package/src/endpoint-generators/create-post-endpoint.ts +13 -23
  188. package/src/endpoint-generators/utils.ts +36 -28
  189. package/src/endpoint-generators/with-schema-and-openapi-action.ts +0 -3
  190. package/src/get-schema-from-api.spec.ts +1 -1
  191. package/src/get-schema-from-api.ts +1 -1
  192. package/src/helpers.spec.ts +51 -41
  193. package/src/helpers.ts +140 -109
  194. package/src/http-authentication-settings.ts +51 -25
  195. package/src/http-server-pool.spec.ts +220 -0
  196. package/src/http-server-pool.ts +169 -0
  197. package/src/http-user-context.spec.ts +203 -383
  198. package/src/http-user-context.ts +114 -91
  199. package/src/index.ts +6 -4
  200. package/src/login-response-strategy.spec.ts +32 -31
  201. package/src/login-response-strategy.ts +13 -12
  202. package/src/openapi/generate-openapi-document.ts +0 -3
  203. package/src/proxy-manager.spec.ts +152 -182
  204. package/src/proxy-runtime.spec.ts +50 -0
  205. package/src/proxy-runtime.ts +75 -0
  206. package/src/rest-api-runtime.spec.ts +77 -0
  207. package/src/rest-api-runtime.ts +204 -0
  208. package/src/rest-service.integration.spec.ts +68 -87
  209. package/src/rest.integration.test.ts +27 -87
  210. package/src/server-telemetry.spec.ts +56 -0
  211. package/src/server-telemetry.ts +51 -0
  212. package/src/static-server-manager.spec.ts +63 -151
  213. package/src/static-site-runtime.spec.ts +39 -0
  214. package/src/static-site-runtime.ts +75 -0
  215. package/src/user-store.spec.ts +86 -0
  216. package/src/user-store.ts +68 -0
  217. package/src/validate.integration.spec.ts +39 -97
  218. package/esm/actions/login-action.spec.d.ts +0 -2
  219. package/esm/actions/login-action.spec.d.ts.map +0 -1
  220. package/esm/actions/login-action.spec.js +0 -34
  221. package/esm/actions/login-action.spec.js.map +0 -1
  222. package/esm/actions/login.d.ts +0 -19
  223. package/esm/actions/login.d.ts.map +0 -1
  224. package/esm/actions/login.js +0 -27
  225. package/esm/actions/login.js.map +0 -1
  226. package/esm/api-manager.d.ts +0 -104
  227. package/esm/api-manager.d.ts.map +0 -1
  228. package/esm/api-manager.js +0 -180
  229. package/esm/api-manager.js.map +0 -1
  230. package/esm/proxy-manager.d.ts +0 -53
  231. package/esm/proxy-manager.d.ts.map +0 -1
  232. package/esm/proxy-manager.js +0 -84
  233. package/esm/proxy-manager.js.map +0 -1
  234. package/esm/server-manager.d.ts +0 -48
  235. package/esm/server-manager.d.ts.map +0 -1
  236. package/esm/server-manager.js +0 -100
  237. package/esm/server-manager.js.map +0 -1
  238. package/esm/static-server-manager.d.ts +0 -19
  239. package/esm/static-server-manager.d.ts.map +0 -1
  240. package/esm/static-server-manager.js +0 -65
  241. package/esm/static-server-manager.js.map +0 -1
  242. package/esm/swagger/generate-swagger-json.spec.d.ts +0 -2
  243. package/esm/swagger/generate-swagger-json.spec.d.ts.map +0 -1
  244. package/esm/swagger/generate-swagger-json.spec.js +0 -215
  245. package/esm/swagger/generate-swagger-json.spec.js.map +0 -1
  246. package/src/actions/login-action.spec.ts +0 -42
  247. package/src/actions/login.ts +0 -32
  248. package/src/api-manager.ts +0 -308
  249. package/src/proxy-manager.ts +0 -102
  250. package/src/server-manager.ts +0 -135
  251. package/src/static-server-manager.ts +0 -90
  252. package/src/swagger/generate-swagger-json.spec.ts +0 -250
@@ -1,10 +1,16 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
- import { getStoreManager, InMemoryStore, User } from '@furystack/core'
2
+ import { InMemoryStore, User as UserModel } from '@furystack/core'
3
3
  import { getPort } from '@furystack/core/port-generator'
4
- import { Injector } from '@furystack/inject'
5
- import { getRepository } from '@furystack/repository'
4
+ import { createInjector } from '@furystack/inject'
6
5
  import type { OpenApiDocument, WithSchemaAction } from '@furystack/rest'
7
6
  import { createClient, ResponseError } from '@furystack/rest-client-fetch'
7
+ import {
8
+ PasswordCredential,
9
+ PasswordCredentialStore,
10
+ PasswordResetToken,
11
+ PasswordResetTokenStore,
12
+ usePasswordPolicy,
13
+ } from '@furystack/security'
8
14
  import { usingAsync } from '@furystack/utils'
9
15
  import type Ajv from 'ajv'
10
16
  import { describe, expect, it } from 'vitest'
@@ -13,10 +19,11 @@ import { createGetCollectionEndpoint } from './endpoint-generators/create-get-co
13
19
  import { createGetEntityEndpoint } from './endpoint-generators/create-get-entity-endpoint.js'
14
20
  import { createPatchEndpoint } from './endpoint-generators/create-patch-endpoint.js'
15
21
  import { createPostEndpoint } from './endpoint-generators/create-post-endpoint.js'
16
- import { MockClass } from './endpoint-generators/utils.js'
22
+ import { MockDataSet, setupContext } from './endpoint-generators/utils.js'
17
23
  import { useHttpAuthentication, useRestService } from './helpers.js'
18
24
  import { DefaultSession } from './models/default-session.js'
19
25
  import { JsonResult } from './request-action-implementation.js'
26
+ import { SessionStore, UserStore } from './user-store.js'
20
27
  import type { ValidationApi } from './validate.integration.schema.js'
21
28
  import schema from './validate.integration.spec.schema.json' with { type: 'json' }
22
29
  import { Validate } from './validate.js'
@@ -28,15 +35,12 @@ const description = crypto.randomUUID()
28
35
  const version = crypto.randomUUID()
29
36
 
30
37
  const createValidateApi = async (options = { enableGetSchema: false }) => {
31
- const injector = new Injector()
38
+ const injector = createInjector()
32
39
  const port = getPort()
33
40
 
34
- getStoreManager(injector).addStore(new InMemoryStore({ model: User, primaryKey: 'username' }))
35
- getStoreManager(injector).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
36
- getStoreManager(injector).addStore(new InMemoryStore({ model: MockClass, primaryKey: 'id' }))
37
- getRepository(injector).createDataSet(MockClass, 'id')
38
- getRepository(injector).createDataSet(User, 'username')
39
- getRepository(injector).createDataSet(DefaultSession, 'sessionId')
41
+ injector.bind(UserStore, () => new InMemoryStore({ model: UserModel, primaryKey: 'username' }))
42
+ injector.bind(SessionStore, () => new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
43
+ setupContext(injector)
40
44
 
41
45
  const api = await useRestService<ValidationApi>({
42
46
  injector,
@@ -61,11 +65,11 @@ const createValidateApi = async (options = { enableGetSchema: false }) => {
61
65
  '/mock': Validate({
62
66
  schema,
63
67
  schemaName: 'GetMockCollectionEndpoint',
64
- })(createGetCollectionEndpoint({ model: MockClass, primaryKey: 'id' })),
68
+ })(createGetCollectionEndpoint(MockDataSet)),
65
69
  '/mock/:id': Validate({
66
70
  schema,
67
71
  schemaName: 'GetMockEntityEndpoint',
68
- })(createGetEntityEndpoint({ model: MockClass, primaryKey: 'id' })),
72
+ })(createGetEntityEndpoint(MockDataSet)),
69
73
  },
70
74
  POST: {
71
75
  '/validate-body': Validate({
@@ -78,19 +82,19 @@ const createValidateApi = async (options = { enableGetSchema: false }) => {
78
82
  '/mock': Validate({
79
83
  schema,
80
84
  schemaName: 'PostMockEndpoint',
81
- })(createPostEndpoint({ model: MockClass, primaryKey: 'id' })),
85
+ })(createPostEndpoint(MockDataSet)),
82
86
  },
83
87
  PATCH: {
84
88
  '/mock/:id': Validate({
85
89
  schema,
86
90
  schemaName: 'PatchMockEndpoint',
87
- })(createPatchEndpoint({ model: MockClass, primaryKey: 'id' })),
91
+ })(createPatchEndpoint(MockDataSet)),
88
92
  },
89
93
  DELETE: {
90
94
  '/mock/:id': Validate({
91
95
  schema,
92
96
  schemaName: 'DeleteMockEndpoint',
93
- })(createDeleteEndpoint({ model: MockClass, primaryKey: 'id' })),
97
+ })(createDeleteEndpoint(MockDataSet)),
94
98
  },
95
99
  },
96
100
  port,
@@ -179,51 +183,6 @@ describe('Validation integration tests', () => {
179
183
  })
180
184
  })
181
185
 
182
- describe('swagger.json backward compatibility', () => {
183
- it('Should serve the same OpenAPI document at /swagger.json when enabled', async () => {
184
- await usingAsync(await createValidateApi({ enableGetSchema: true }), async ({ client }) => {
185
- const result = await (client as ReturnType<typeof createClient<any>>)({
186
- method: 'GET',
187
- action: '/swagger.json',
188
- })
189
-
190
- expect(result.response.status).toBe(200)
191
- expect(result.result).toBeDefined()
192
-
193
- const openApiDoc = result.result as OpenApiDocument
194
- expect(openApiDoc.openapi).toBe('3.1.0')
195
- expect(openApiDoc.info?.title).toBe(name)
196
- })
197
- })
198
-
199
- it('Should include Deprecation header on /swagger.json', async () => {
200
- await usingAsync(await createValidateApi({ enableGetSchema: true }), async ({ client }) => {
201
- const result = await (client as ReturnType<typeof createClient<any>>)({
202
- method: 'GET',
203
- action: '/swagger.json',
204
- })
205
-
206
- expect(result.response.headers.get('deprecation')).toBe('true')
207
- expect(result.response.headers.get('link')).toContain('/openapi.json')
208
- })
209
- })
210
-
211
- it('Should return a 404 for /swagger.json when not enabled', async () => {
212
- await usingAsync(await createValidateApi({ enableGetSchema: false }), async ({ client }) => {
213
- try {
214
- await (client as ReturnType<typeof createClient<any>>)({
215
- method: 'GET',
216
- action: '/swagger.json',
217
- })
218
- expect.fail('Expected response error but got success')
219
- } catch (error) {
220
- expect(error).toBeInstanceOf(ResponseError)
221
- expect((error as ResponseError).response.status).toBe(404)
222
- }
223
- })
224
- })
225
- })
226
-
227
186
  describe('Validation metadata', () => {
228
187
  it('Should return 404 when not enabled', async () => {
229
188
  expect.assertions(2)
@@ -492,16 +451,22 @@ describe('Validation integration tests', () => {
492
451
 
493
452
  describe('OpenAPI security schemes from authentication providers', () => {
494
453
  const createApiWithAuth = async () => {
495
- const injector = new Injector()
454
+ const injector = createInjector()
496
455
  const port = getPort()
497
456
 
498
- getStoreManager(injector).addStore(new InMemoryStore({ model: User, primaryKey: 'username' }))
499
- getStoreManager(injector).addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
500
- getStoreManager(injector).addStore(new InMemoryStore({ model: MockClass, primaryKey: 'id' }))
501
- getRepository(injector).createDataSet(MockClass, 'id')
502
- getRepository(injector).createDataSet(User, 'username')
503
- getRepository(injector).createDataSet(DefaultSession, 'sessionId')
504
-
457
+ injector.bind(UserStore, () => new InMemoryStore({ model: UserModel, primaryKey: 'username' }))
458
+ injector.bind(SessionStore, () => new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
459
+ injector.bind(
460
+ PasswordCredentialStore,
461
+ () => new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }),
462
+ )
463
+ injector.bind(
464
+ PasswordResetTokenStore,
465
+ () => new InMemoryStore({ model: PasswordResetToken, primaryKey: 'token' }),
466
+ )
467
+ setupContext(injector)
468
+
469
+ usePasswordPolicy(injector)
505
470
  useHttpAuthentication(injector)
506
471
 
507
472
  await useRestService<ValidationApi>({
@@ -522,10 +487,10 @@ describe('Validation integration tests', () => {
522
487
  JsonResult({ ...headers }),
523
488
  ),
524
489
  '/mock': Validate({ schema, schemaName: 'GetMockCollectionEndpoint' })(
525
- createGetCollectionEndpoint({ model: MockClass, primaryKey: 'id' }),
490
+ createGetCollectionEndpoint(MockDataSet),
526
491
  ),
527
492
  '/mock/:id': Validate({ schema, schemaName: 'GetMockEntityEndpoint' })(
528
- createGetEntityEndpoint({ model: MockClass, primaryKey: 'id' }),
493
+ createGetEntityEndpoint(MockDataSet),
529
494
  ),
530
495
  },
531
496
  POST: {
@@ -533,19 +498,13 @@ describe('Validation integration tests', () => {
533
498
  const body = await getBody()
534
499
  return JsonResult({ ...body })
535
500
  }),
536
- '/mock': Validate({ schema, schemaName: 'PostMockEndpoint' })(
537
- createPostEndpoint({ model: MockClass, primaryKey: 'id' }),
538
- ),
501
+ '/mock': Validate({ schema, schemaName: 'PostMockEndpoint' })(createPostEndpoint(MockDataSet)),
539
502
  },
540
503
  PATCH: {
541
- '/mock/:id': Validate({ schema, schemaName: 'PatchMockEndpoint' })(
542
- createPatchEndpoint({ model: MockClass, primaryKey: 'id' }),
543
- ),
504
+ '/mock/:id': Validate({ schema, schemaName: 'PatchMockEndpoint' })(createPatchEndpoint(MockDataSet)),
544
505
  },
545
506
  DELETE: {
546
- '/mock/:id': Validate({ schema, schemaName: 'DeleteMockEndpoint' })(
547
- createDeleteEndpoint({ model: MockClass, primaryKey: 'id' }),
548
- ),
507
+ '/mock/:id': Validate({ schema, schemaName: 'DeleteMockEndpoint' })(createDeleteEndpoint(MockDataSet)),
549
508
  },
550
509
  },
551
510
  port,
@@ -577,22 +536,5 @@ describe('Validation integration tests', () => {
577
536
  })
578
537
  })
579
538
  })
580
-
581
- it('Should include detected security schemes in the deprecated /swagger.json endpoint', async () => {
582
- await usingAsync(await createApiWithAuth(), async ({ client }) => {
583
- const result = await (client as ReturnType<typeof createClient<any>>)({
584
- method: 'GET',
585
- action: '/swagger.json',
586
- })
587
-
588
- const openApiDoc = result.result as OpenApiDocument
589
- expect(openApiDoc.components?.securitySchemes?.basicAuth).toEqual({ type: 'http', scheme: 'basic' })
590
- expect(openApiDoc.components?.securitySchemes?.cookieAuth).toEqual({
591
- type: 'apiKey',
592
- in: 'cookie',
593
- name: 'session',
594
- })
595
- })
596
- })
597
539
  })
598
540
  })
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=login-action.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-action.spec.d.ts","sourceRoot":"","sources":["../../src/actions/login-action.spec.ts"],"names":[],"mappings":""}
@@ -1,34 +0,0 @@
1
- import { Injector } from '@furystack/inject';
2
- import { usingAsync } from '@furystack/utils';
3
- import { describe, expect, it, vi } from 'vitest';
4
- import { HttpUserContext } from '../http-user-context.js';
5
- import { LoginAction } from './login.js';
6
- describe('LoginAction', () => {
7
- const request = { url: 'https://google.com' };
8
- const response = {};
9
- it('Returns the provided user with 200 on success', async () => {
10
- const testUser = { Name: 'Userke' };
11
- await usingAsync(new Injector(), async (i) => {
12
- i.setExplicitInstance({
13
- authenticateUser: vi.fn(async () => testUser),
14
- cookieLogin: vi.fn(async () => testUser),
15
- authentication: {},
16
- }, HttpUserContext);
17
- const result = await LoginAction({
18
- request,
19
- response,
20
- injector: i,
21
- getBody: async () => ({ username: 'testuser', password: 'alma' }),
22
- });
23
- expect(result.chunk).toEqual(testUser);
24
- expect(result.statusCode).toBe(200);
25
- });
26
- });
27
- it('Returns throw error with 400 on fail', async () => {
28
- await usingAsync(new Injector(), async (i) => {
29
- i.setExplicitInstance({ cookieLogin: async () => Promise.reject(new Error(':(')) }, HttpUserContext);
30
- await expect(LoginAction({ request, response, injector: i, getBody: async () => ({ username: '', password: '' }) })).rejects.toThrowError('Login Failed');
31
- });
32
- });
33
- });
34
- //# sourceMappingURL=login-action.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-action.spec.js","sourceRoot":"","sources":["../../src/actions/login-action.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAExC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAqB,CAAA;IAChE,MAAM,QAAQ,GAAG,EAAoB,CAAA;IAErC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;QACnC,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,CAAC,CAAC,mBAAmB,CACnB;gBACE,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC;gBAC7C,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC;gBACxC,cAAc,EAAE,EAAE;aACnB,EACD,eAAe,CAChB,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;gBAC/B,OAAO;gBACP,QAAQ;gBACR,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;aAClE,CAAC,CAAA;YACF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YACtC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACrC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC3C,CAAC,CAAC,mBAAmB,CAAC,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC,CAAA;YACpG,MAAM,MAAM,CACV,WAAW,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CACvG,CAAC,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,19 +0,0 @@
1
- import type { User } from '@furystack/core';
2
- import type { RequestAction } from '../request-action-implementation.js';
3
- /**
4
- * Action that logs in the current user.
5
- * Should be called with a JSON POST body with `username` and `password` fields.
6
- * Returns the current user instance.
7
- *
8
- * @deprecated Use `createPasswordLoginAction(createCookieLoginStrategy(injector))` instead.
9
- * This static action resolves services from the request-scoped injector on
10
- * every call; the factory approach captures them once at setup time.
11
- */
12
- export declare const LoginAction: RequestAction<{
13
- result: User;
14
- body: {
15
- username: string;
16
- password: string;
17
- };
18
- }>;
19
- //# sourceMappingURL=login.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/actions/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAK3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AAGxE;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC;IACtC,MAAM,EAAE,IAAI,CAAA;IACZ,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7C,CAWA,CAAA"}
@@ -1,27 +0,0 @@
1
- import { RequestError } from '@furystack/rest';
2
- import { sleepAsync } from '@furystack/utils';
3
- import { HttpUserContext } from '../http-user-context.js';
4
- import { JsonResult } from '../request-action-implementation.js';
5
- /**
6
- * Action that logs in the current user.
7
- * Should be called with a JSON POST body with `username` and `password` fields.
8
- * Returns the current user instance.
9
- *
10
- * @deprecated Use `createPasswordLoginAction(createCookieLoginStrategy(injector))` instead.
11
- * This static action resolves services from the request-scoped injector on
12
- * every call; the factory approach captures them once at setup time.
13
- */
14
- export const LoginAction = async ({ injector, getBody, response }) => {
15
- const userContext = injector.getInstance(HttpUserContext);
16
- const body = await getBody();
17
- try {
18
- const user = await userContext.authenticateUser(body.username, body.password);
19
- await userContext.cookieLogin(user, response);
20
- return JsonResult(user, 200);
21
- }
22
- catch {
23
- await sleepAsync(Math.random() * 1000);
24
- throw new RequestError('Login Failed', 400);
25
- }
26
- };
27
- //# sourceMappingURL=login.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/actions/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAA;AAEhE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,WAAW,GAGnB,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;IACzD,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAA;IAC5B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC7E,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC7C,OAAO,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;QACtC,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC,CAAA"}
@@ -1,104 +0,0 @@
1
- import type { Injector } from '@furystack/inject';
2
- import type { Method, RestApi } from '@furystack/rest';
3
- import type { MatchFunction } from 'path-to-regexp';
4
- import type { CorsOptions } from './models/cors-options.js';
5
- import type { RequestAction } from './request-action-implementation.js';
6
- import type { OnRequest } from './server-manager.js';
7
- import './server-response-extensions.js';
8
- export type RestApiImplementation<T extends RestApi> = {
9
- [TMethod in keyof T]: {
10
- [TUrl in keyof T[TMethod]]: T[TMethod][TUrl] extends {
11
- result: unknown;
12
- } ? RequestAction<T[TMethod][TUrl]> : never;
13
- };
14
- };
15
- export interface ImplementApiOptions<T extends RestApi> {
16
- /**
17
- * The structure of the implemented API.
18
- */
19
- api: RestApiImplementation<T>;
20
- /**
21
- * The Injector instance to use for dependency injection in the API actions.
22
- */
23
- injector: Injector;
24
- /**
25
- * The host name for the API Server. If not provided, the default host (ServerManager.DEFAULT_HOST) will be used.
26
- */
27
- hostName?: string;
28
- /**
29
- * The root path for the API. This will be prepended to all API paths.
30
- */
31
- root: string;
32
- /**
33
- * The port on which the API server will listen.
34
- */
35
- port: number;
36
- /**
37
- * CORS options to configure Cross-Origin Resource Sharing for the API.
38
- */
39
- cors?: CorsOptions;
40
- /**
41
- * An optional function to deserialize query parameters from the URL.
42
- * This function should take a query string (e.g., "?key=value") and return an object with the parsed parameters.
43
- * If not provided, the default deserialization will be used.
44
- */
45
- deserializeQueryParams?: (param: string) => any;
46
- /**
47
- * Adds an additional 'GET /schema' endpoint that returns the schema definitions of the API.
48
- * Also adds a 'GET /openapi.json' endpoint that returns the API schema in OpenAPI 3.1 format.
49
- */
50
- enableGetSchema?: boolean;
51
- /**
52
- * Optional name for the API, used in the generated schema.
53
- * This can be useful for documentation or identification purposes.
54
- */
55
- name?: string;
56
- /**
57
- * Optional description for the API, used in the generated schema.
58
- * This can provide additional context or information about the API's purpose.
59
- */
60
- description?: string;
61
- /**
62
- * Optional version for the API, used in the generated schema.
63
- * This can help in versioning the API and tracking changes over time.
64
- */
65
- version?: string;
66
- }
67
- export type NewCompiledApiEntry = {
68
- method: Method;
69
- fullPath: string;
70
- matcher: MatchFunction<Partial<Record<string, string | string[]>>>;
71
- action: RequestAction<any>;
72
- };
73
- export type NewCompiledApi = {
74
- [K in Method]?: NewCompiledApiEntry[];
75
- };
76
- export type OnRequestOptions = OnRequest & {
77
- compiledApi: NewCompiledApi;
78
- hostName?: string;
79
- port: number;
80
- rootApiPath: string;
81
- injector: Injector;
82
- cors?: CorsOptions;
83
- supportedMethods: string[];
84
- deserializeQueryParams?: (param: string) => Record<string, unknown>;
85
- };
86
- export declare class ApiManager {
87
- private getSuportedMethods;
88
- private compileApi;
89
- addApi<T extends RestApi>({ api, hostName, port, root, cors, injector, deserializeQueryParams, enableGetSchema, name, description, version, }: ImplementApiOptions<T>): Promise<{
90
- shouldExec: (msg: OnRequest) => boolean;
91
- onRequest: (msg: OnRequest) => Promise<void>;
92
- }>;
93
- shouldExecRequest(options: {
94
- method?: Method;
95
- url?: string;
96
- rootApiPath: string;
97
- supportedMethods: Method[];
98
- }): boolean;
99
- private getActionFromEndpoint;
100
- private executeAction;
101
- private onMessage;
102
- private readonly serverManager;
103
- }
104
- //# sourceMappingURL=api-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-manager.d.ts","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":"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"}
@@ -1,180 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { IdentityContext } from '@furystack/core';
11
- import { Injectable, Injected } from '@furystack/inject';
12
- import { RequestError, deserializeQueryString } from '@furystack/rest';
13
- import { PathHelper, usingAsync } from '@furystack/utils';
14
- import { match } from 'path-to-regexp';
15
- import { ErrorAction } from './actions/error-action.js';
16
- import { NotFoundAction } from './actions/not-found-action.js';
17
- import { addCorsHeaders } from './add-cors-header.js';
18
- import { CreateGetSchemaAction } from './endpoint-generators/create-get-schema-action.js';
19
- import { CreateGetOpenApiDocumentAction, CreateDeprecatedSwaggerRedirect, } from './endpoint-generators/create-get-openapi-document-action.js';
20
- import { HttpUserContext } from './http-user-context.js';
21
- import { readPostBody } from './read-post-body.js';
22
- import { ServerManager } from './server-manager.js';
23
- import './server-response-extensions.js';
24
- let ApiManager = class ApiManager {
25
- getSuportedMethods(api) {
26
- return Object.keys(api);
27
- }
28
- compileApi(api, root) {
29
- const supportedMethods = this.getSuportedMethods(api);
30
- const compiledApi = {};
31
- supportedMethods.forEach((method) => {
32
- compiledApi[method] = [
33
- ...Object.entries(api[method]).map(([path, action]) => {
34
- const fullPath = `/${PathHelper.normalize(PathHelper.joinPaths(root, path))}`;
35
- const matcher = match(fullPath, { decode: decodeURIComponent });
36
- return { method, fullPath, matcher, action: action };
37
- }),
38
- ];
39
- });
40
- return compiledApi;
41
- }
42
- async addApi({ api, hostName, port, root, cors, injector, deserializeQueryParams, enableGetSchema, name, description, version, }) {
43
- const extendedApi = enableGetSchema
44
- ? {
45
- ...api,
46
- GET: {
47
- ...api.GET,
48
- '/schema': CreateGetSchemaAction(api, name, description, version),
49
- '/openapi.json': CreateGetOpenApiDocumentAction(api, name, description, version),
50
- '/swagger.json': CreateDeprecatedSwaggerRedirect(api, name, description, version),
51
- },
52
- }
53
- : api;
54
- const supportedMethods = this.getSuportedMethods(extendedApi);
55
- const rootApiPath = PathHelper.normalize(root);
56
- const server = await this.serverManager.getOrCreate({ hostName, port });
57
- const compiledApi = this.compileApi(extendedApi, root);
58
- const serverApi = {
59
- shouldExec: (msg) => this.shouldExecRequest({
60
- ...msg,
61
- method: msg.req.method?.toUpperCase(),
62
- rootApiPath,
63
- supportedMethods,
64
- url: PathHelper.normalize(msg.req.url || ''),
65
- }),
66
- onRequest: (msg) => this.onMessage({
67
- ...msg,
68
- compiledApi,
69
- rootApiPath,
70
- port,
71
- supportedMethods,
72
- cors,
73
- injector,
74
- hostName,
75
- deserializeQueryParams,
76
- }),
77
- };
78
- server.apis.push(serverApi);
79
- return serverApi;
80
- }
81
- shouldExecRequest(options) {
82
- return options.method &&
83
- options.url &&
84
- (options.supportedMethods.includes(options.method) || options.method === 'OPTIONS') &&
85
- PathHelper.matchesBaseUrl(options.url, options.rootApiPath)
86
- ? true
87
- : false;
88
- }
89
- getActionFromEndpoint(compiledEndpoint, fullUrl, method) {
90
- let resolvedParams;
91
- const action = compiledEndpoint[method]?.find((route) => {
92
- const result = route.matcher(fullUrl.pathname);
93
- if (result) {
94
- resolvedParams = result.params;
95
- }
96
- return result;
97
- });
98
- return (action && {
99
- ...action,
100
- params: resolvedParams,
101
- });
102
- }
103
- async executeAction({ injector, req, res, fullUrl, action, deserializeQueryParams, params, }) {
104
- await usingAsync(injector.createChild({ owner: action }), async (i) => {
105
- const httpUserContext = i.getInstance(HttpUserContext);
106
- i.setExplicitInstance({
107
- getCurrentUser: () => httpUserContext.getCurrentUser(req),
108
- isAuthorized: (...roles) => httpUserContext.isAuthorized(req, ...roles),
109
- isAuthenticated: () => httpUserContext.isAuthenticated(req),
110
- }, IdentityContext);
111
- try {
112
- const actionResult = await action({
113
- request: req,
114
- response: res,
115
- injector: i,
116
- getBody: () => readPostBody(req),
117
- headers: req.headers,
118
- getQuery: () => deserializeQueryParams ? deserializeQueryParams(fullUrl.search) : deserializeQueryString(fullUrl.search),
119
- getUrlParams: () => {
120
- return params;
121
- },
122
- });
123
- res.sendActionResult(actionResult);
124
- }
125
- catch (error) {
126
- const errorActionResult = await ErrorAction({
127
- request: req,
128
- response: res,
129
- injector: i,
130
- getBody: async () => error,
131
- });
132
- res.sendActionResult(errorActionResult);
133
- }
134
- return;
135
- });
136
- }
137
- async onMessage(options) {
138
- const protocol = 'http://';
139
- const host = `${options.hostName || ServerManager.DEFAULT_HOST}:${options.port}`;
140
- const fullUrl = new URL(PathHelper.joinUrl(`${protocol}${host}`, options.req.url));
141
- if (options.cors) {
142
- addCorsHeaders(options.cors, options.req, options.res);
143
- }
144
- if (options.req.method === 'OPTIONS') {
145
- options.res.writeHead(200);
146
- options.res.end();
147
- return;
148
- }
149
- let action;
150
- try {
151
- action = this.getActionFromEndpoint(options.compiledApi, fullUrl, options.req.method?.toUpperCase());
152
- }
153
- catch (error) {
154
- const responseError = error instanceof URIError ? new RequestError('Failed to decode URL path parameter', 400) : error;
155
- const errorActionResult = await ErrorAction({
156
- request: options.req,
157
- response: options.res,
158
- injector: options.injector,
159
- getBody: async () => responseError,
160
- });
161
- options.res.sendActionResult(errorActionResult);
162
- return;
163
- }
164
- if (action) {
165
- await this.executeAction({ ...options, ...action, fullUrl });
166
- }
167
- else {
168
- options.res.sendActionResult(await NotFoundAction({ injector: options.injector, request: options.req, response: options.res }));
169
- }
170
- }
171
- };
172
- __decorate([
173
- Injected(ServerManager),
174
- __metadata("design:type", ServerManager)
175
- ], ApiManager.prototype, "serverManager", void 0);
176
- ApiManager = __decorate([
177
- Injectable({ lifetime: 'singleton' })
178
- ], ApiManager);
179
- export { ApiManager };
180
- //# sourceMappingURL=api-manager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-manager.js","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":"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"}