@furystack/rest-service 4.0.19

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 (285) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +219 -0
  3. package/dist/actions/error-action.d.ts +14 -0
  4. package/dist/actions/error-action.d.ts.map +1 -0
  5. package/dist/actions/error-action.js +29 -0
  6. package/dist/actions/error-action.js.map +1 -0
  7. package/dist/actions/error-action.spec.d.ts +2 -0
  8. package/dist/actions/error-action.spec.d.ts.map +1 -0
  9. package/dist/actions/error-action.spec.js +51 -0
  10. package/dist/actions/error-action.spec.js.map +1 -0
  11. package/dist/actions/get-current-user.d.ts +11 -0
  12. package/dist/actions/get-current-user.d.ts.map +1 -0
  13. package/dist/actions/get-current-user.js +15 -0
  14. package/dist/actions/get-current-user.js.map +1 -0
  15. package/dist/actions/get-current-user.spec.d.ts +2 -0
  16. package/dist/actions/get-current-user.spec.d.ts.map +1 -0
  17. package/dist/actions/get-current-user.spec.js +20 -0
  18. package/dist/actions/get-current-user.spec.js.map +1 -0
  19. package/dist/actions/index.d.ts +7 -0
  20. package/dist/actions/index.d.ts.map +1 -0
  21. package/dist/actions/index.js +10 -0
  22. package/dist/actions/index.js.map +1 -0
  23. package/dist/actions/is-authenticated.d.ts +14 -0
  24. package/dist/actions/is-authenticated.d.ts.map +1 -0
  25. package/dist/actions/is-authenticated.js +17 -0
  26. package/dist/actions/is-authenticated.js.map +1 -0
  27. package/dist/actions/is-authenticated.spec.d.ts +2 -0
  28. package/dist/actions/is-authenticated.spec.d.ts.map +1 -0
  29. package/dist/actions/is-authenticated.spec.js +19 -0
  30. package/dist/actions/is-authenticated.spec.js.map +1 -0
  31. package/dist/actions/login-action.spec.d.ts +2 -0
  32. package/dist/actions/login-action.spec.d.ts.map +1 -0
  33. package/dist/actions/login-action.spec.js +35 -0
  34. package/dist/actions/login-action.spec.js.map +1 -0
  35. package/dist/actions/login.d.ts +16 -0
  36. package/dist/actions/login.d.ts.map +1 -0
  37. package/dist/actions/login.js +26 -0
  38. package/dist/actions/login.js.map +1 -0
  39. package/dist/actions/logout-action.spec.d.ts +2 -0
  40. package/dist/actions/logout-action.spec.d.ts.map +1 -0
  41. package/dist/actions/logout-action.spec.js +23 -0
  42. package/dist/actions/logout-action.spec.js.map +1 -0
  43. package/dist/actions/logout.d.ts +14 -0
  44. package/dist/actions/logout.d.ts.map +1 -0
  45. package/dist/actions/logout.js +20 -0
  46. package/dist/actions/logout.js.map +1 -0
  47. package/dist/actions/not-found-action.d.ts +10 -0
  48. package/dist/actions/not-found-action.d.ts.map +1 -0
  49. package/dist/actions/not-found-action.js +14 -0
  50. package/dist/actions/not-found-action.js.map +1 -0
  51. package/dist/actions/not-found-action.spec.d.ts +2 -0
  52. package/dist/actions/not-found-action.spec.d.ts.map +1 -0
  53. package/dist/actions/not-found-action.spec.js +17 -0
  54. package/dist/actions/not-found-action.spec.js.map +1 -0
  55. package/dist/add-cors-header.spec.d.ts +2 -0
  56. package/dist/add-cors-header.spec.d.ts.map +1 -0
  57. package/dist/add-cors-header.spec.js +99 -0
  58. package/dist/add-cors-header.spec.js.map +1 -0
  59. package/dist/api-manager.d.ts +61 -0
  60. package/dist/api-manager.d.ts.map +1 -0
  61. package/dist/api-manager.js +144 -0
  62. package/dist/api-manager.js.map +1 -0
  63. package/dist/authenticate.d.ts +5 -0
  64. package/dist/authenticate.d.ts.map +1 -0
  65. package/dist/authenticate.js +20 -0
  66. package/dist/authenticate.js.map +1 -0
  67. package/dist/authenticate.spec.d.ts +2 -0
  68. package/dist/authenticate.spec.d.ts.map +1 -0
  69. package/dist/authenticate.spec.js +59 -0
  70. package/dist/authenticate.spec.js.map +1 -0
  71. package/dist/authorize.d.ts +5 -0
  72. package/dist/authorize.d.ts.map +1 -0
  73. package/dist/authorize.js +22 -0
  74. package/dist/authorize.js.map +1 -0
  75. package/dist/authorize.spec.d.ts +2 -0
  76. package/dist/authorize.spec.d.ts.map +1 -0
  77. package/dist/authorize.spec.js +55 -0
  78. package/dist/authorize.spec.js.map +1 -0
  79. package/dist/endpoint-generators/create-delete-endpoint.d.ts +17 -0
  80. package/dist/endpoint-generators/create-delete-endpoint.d.ts.map +1 -0
  81. package/dist/endpoint-generators/create-delete-endpoint.js +24 -0
  82. package/dist/endpoint-generators/create-delete-endpoint.js.map +1 -0
  83. package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts +2 -0
  84. package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts.map +1 -0
  85. package/dist/endpoint-generators/create-delete-endpoint.spec.js +33 -0
  86. package/dist/endpoint-generators/create-delete-endpoint.spec.js.map +1 -0
  87. package/dist/endpoint-generators/create-get-collection-endpoint.d.ts +17 -0
  88. package/dist/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -0
  89. package/dist/endpoint-generators/create-get-collection-endpoint.js +26 -0
  90. package/dist/endpoint-generators/create-get-collection-endpoint.js.map +1 -0
  91. package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts +2 -0
  92. package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts.map +1 -0
  93. package/dist/endpoint-generators/create-get-collection-endpoint.spec.js +143 -0
  94. package/dist/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -0
  95. package/dist/endpoint-generators/create-get-entity-endpoint.d.ts +17 -0
  96. package/dist/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -0
  97. package/dist/endpoint-generators/create-get-entity-endpoint.js +29 -0
  98. package/dist/endpoint-generators/create-get-entity-endpoint.js.map +1 -0
  99. package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts +2 -0
  100. package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts.map +1 -0
  101. package/dist/endpoint-generators/create-get-entity-endpoint.spec.js +74 -0
  102. package/dist/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -0
  103. package/dist/endpoint-generators/create-patch-endpoint.d.ts +18 -0
  104. package/dist/endpoint-generators/create-patch-endpoint.d.ts.map +1 -0
  105. package/dist/endpoint-generators/create-patch-endpoint.js +26 -0
  106. package/dist/endpoint-generators/create-patch-endpoint.js.map +1 -0
  107. package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts +2 -0
  108. package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts.map +1 -0
  109. package/dist/endpoint-generators/create-patch-endpoint.spec.js +36 -0
  110. package/dist/endpoint-generators/create-patch-endpoint.spec.js.map +1 -0
  111. package/dist/endpoint-generators/create-post-endpoint.d.ts +18 -0
  112. package/dist/endpoint-generators/create-post-endpoint.d.ts.map +1 -0
  113. package/dist/endpoint-generators/create-post-endpoint.js +29 -0
  114. package/dist/endpoint-generators/create-post-endpoint.js.map +1 -0
  115. package/dist/endpoint-generators/create-post-endpoint.spec.d.ts +2 -0
  116. package/dist/endpoint-generators/create-post-endpoint.spec.d.ts.map +1 -0
  117. package/dist/endpoint-generators/create-post-endpoint.spec.js +34 -0
  118. package/dist/endpoint-generators/create-post-endpoint.spec.js.map +1 -0
  119. package/dist/endpoint-generators/index.d.ts +6 -0
  120. package/dist/endpoint-generators/index.d.ts.map +1 -0
  121. package/dist/endpoint-generators/index.js +9 -0
  122. package/dist/endpoint-generators/index.js.map +1 -0
  123. package/dist/endpoint-generators/utils.d.ts +9 -0
  124. package/dist/endpoint-generators/utils.d.ts.map +1 -0
  125. package/dist/endpoint-generators/utils.js +27 -0
  126. package/dist/endpoint-generators/utils.js.map +1 -0
  127. package/dist/http-authentication-settings.d.ts +17 -0
  128. package/dist/http-authentication-settings.d.ts.map +1 -0
  129. package/dist/http-authentication-settings.js +26 -0
  130. package/dist/http-authentication-settings.js.map +1 -0
  131. package/dist/http-user-context.d.ts +54 -0
  132. package/dist/http-user-context.d.ts.map +1 -0
  133. package/dist/http-user-context.js +153 -0
  134. package/dist/http-user-context.js.map +1 -0
  135. package/dist/http-user-context.spec.d.ts +4 -0
  136. package/dist/http-user-context.spec.d.ts.map +1 -0
  137. package/dist/http-user-context.spec.js +267 -0
  138. package/dist/http-user-context.spec.js.map +1 -0
  139. package/dist/incoming-message-extensions.d.ts +8 -0
  140. package/dist/incoming-message-extensions.d.ts.map +1 -0
  141. package/dist/incoming-message-extensions.js +14 -0
  142. package/dist/incoming-message-extensions.js.map +1 -0
  143. package/dist/incoming-message-extensions.spec.d.ts +2 -0
  144. package/dist/incoming-message-extensions.spec.d.ts.map +1 -0
  145. package/dist/incoming-message-extensions.spec.js +39 -0
  146. package/dist/incoming-message-extensions.spec.js.map +1 -0
  147. package/dist/index.d.ts +17 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +20 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/injector-extensions.d.ts +21 -0
  152. package/dist/injector-extensions.d.ts.map +1 -0
  153. package/dist/injector-extensions.js +14 -0
  154. package/dist/injector-extensions.js.map +1 -0
  155. package/dist/injector-extensions.spec.d.ts +2 -0
  156. package/dist/injector-extensions.spec.d.ts.map +1 -0
  157. package/dist/injector-extensions.spec.js +19 -0
  158. package/dist/injector-extensions.spec.js.map +1 -0
  159. package/dist/models/cors-options.d.ts +22 -0
  160. package/dist/models/cors-options.d.ts.map +1 -0
  161. package/dist/models/cors-options.js +3 -0
  162. package/dist/models/cors-options.js.map +1 -0
  163. package/dist/models/default-session.d.ts +14 -0
  164. package/dist/models/default-session.d.ts.map +1 -0
  165. package/dist/models/default-session.js +10 -0
  166. package/dist/models/default-session.js.map +1 -0
  167. package/dist/request-action-implementation.d.ts +54 -0
  168. package/dist/request-action-implementation.d.ts.map +1 -0
  169. package/dist/request-action-implementation.js +42 -0
  170. package/dist/request-action-implementation.js.map +1 -0
  171. package/dist/rest-service.integration.spec.d.ts +2 -0
  172. package/dist/rest-service.integration.spec.d.ts.map +1 -0
  173. package/dist/rest-service.integration.spec.js +129 -0
  174. package/dist/rest-service.integration.spec.js.map +1 -0
  175. package/dist/rest.integration.test.d.ts +58 -0
  176. package/dist/rest.integration.test.d.ts.map +1 -0
  177. package/dist/rest.integration.test.js +94 -0
  178. package/dist/rest.integration.test.js.map +1 -0
  179. package/dist/schema-validator/index.d.ts +3 -0
  180. package/dist/schema-validator/index.d.ts.map +1 -0
  181. package/dist/schema-validator/index.js +6 -0
  182. package/dist/schema-validator/index.js.map +1 -0
  183. package/dist/schema-validator/schema-validation-error.d.ts +10 -0
  184. package/dist/schema-validator/schema-validation-error.d.ts.map +1 -0
  185. package/dist/schema-validator/schema-validation-error.js +15 -0
  186. package/dist/schema-validator/schema-validation-error.js.map +1 -0
  187. package/dist/schema-validator/schema-validator.d.ts +20 -0
  188. package/dist/schema-validator/schema-validator.d.ts.map +1 -0
  189. package/dist/schema-validator/schema-validator.js +36 -0
  190. package/dist/schema-validator/schema-validator.js.map +1 -0
  191. package/dist/schema-validator/schema-validator.test.d.ts +2 -0
  192. package/dist/schema-validator/schema-validator.test.d.ts.map +1 -0
  193. package/dist/schema-validator/schema-validator.test.js +62 -0
  194. package/dist/schema-validator/schema-validator.test.js.map +1 -0
  195. package/dist/schema-validator/validate-examples.d.ts +37 -0
  196. package/dist/schema-validator/validate-examples.d.ts.map +1 -0
  197. package/dist/schema-validator/validate-examples.js +29 -0
  198. package/dist/schema-validator/validate-examples.js.map +1 -0
  199. package/dist/server-manager.d.ts +30 -0
  200. package/dist/server-manager.d.ts.map +1 -0
  201. package/dist/server-manager.js +71 -0
  202. package/dist/server-manager.js.map +1 -0
  203. package/dist/server-response-extensions.d.ts +21 -0
  204. package/dist/server-response-extensions.d.ts.map +1 -0
  205. package/dist/server-response-extensions.js +15 -0
  206. package/dist/server-response-extensions.js.map +1 -0
  207. package/dist/server-response-extensions.spec.d.ts +2 -0
  208. package/dist/server-response-extensions.spec.d.ts.map +1 -0
  209. package/dist/server-response-extensions.spec.js +49 -0
  210. package/dist/server-response-extensions.spec.js.map +1 -0
  211. package/dist/utils.d.ts +24 -0
  212. package/dist/utils.d.ts.map +1 -0
  213. package/dist/utils.js +66 -0
  214. package/dist/utils.js.map +1 -0
  215. package/dist/validate.d.ts +18 -0
  216. package/dist/validate.d.ts.map +1 -0
  217. package/dist/validate.integration.schema.d.ts +69 -0
  218. package/dist/validate.integration.schema.d.ts.map +1 -0
  219. package/dist/validate.integration.schema.js +3 -0
  220. package/dist/validate.integration.schema.js.map +1 -0
  221. package/dist/validate.integration.spec.d.ts +13 -0
  222. package/dist/validate.integration.spec.d.ts.map +1 -0
  223. package/dist/validate.integration.spec.js +223 -0
  224. package/dist/validate.integration.spec.js.map +1 -0
  225. package/dist/validate.integration.spec.schema.json +749 -0
  226. package/dist/validate.js +49 -0
  227. package/dist/validate.js.map +1 -0
  228. package/package.json +56 -0
  229. package/src/actions/error-action.spec.ts +54 -0
  230. package/src/actions/error-action.ts +34 -0
  231. package/src/actions/get-current-user.spec.ts +23 -0
  232. package/src/actions/get-current-user.ts +15 -0
  233. package/src/actions/index.ts +6 -0
  234. package/src/actions/is-authenticated.spec.ts +18 -0
  235. package/src/actions/is-authenticated.ts +13 -0
  236. package/src/actions/login-action.spec.ts +41 -0
  237. package/src/actions/login.ts +26 -0
  238. package/src/actions/logout-action.spec.ts +27 -0
  239. package/src/actions/logout.ts +16 -0
  240. package/src/actions/not-found-action.spec.ts +17 -0
  241. package/src/actions/not-found-action.ts +13 -0
  242. package/src/add-cors-header.spec.ts +133 -0
  243. package/src/api-manager.ts +222 -0
  244. package/src/authenticate.spec.ts +78 -0
  245. package/src/authenticate.ts +22 -0
  246. package/src/authorize.spec.ts +69 -0
  247. package/src/authorize.ts +19 -0
  248. package/src/endpoint-generators/create-delete-endpoint.spec.ts +34 -0
  249. package/src/endpoint-generators/create-delete-endpoint.ts +25 -0
  250. package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +164 -0
  251. package/src/endpoint-generators/create-get-collection-endpoint.ts +28 -0
  252. package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +75 -0
  253. package/src/endpoint-generators/create-get-entity-endpoint.ts +29 -0
  254. package/src/endpoint-generators/create-patch-endpoint.spec.ts +36 -0
  255. package/src/endpoint-generators/create-patch-endpoint.ts +27 -0
  256. package/src/endpoint-generators/create-post-endpoint.spec.ts +32 -0
  257. package/src/endpoint-generators/create-post-endpoint.ts +30 -0
  258. package/src/endpoint-generators/index.ts +5 -0
  259. package/src/endpoint-generators/utils.ts +34 -0
  260. package/src/http-authentication-settings.ts +23 -0
  261. package/src/http-user-context.spec.ts +299 -0
  262. package/src/http-user-context.ts +160 -0
  263. package/src/incoming-message-extensions.spec.ts +41 -0
  264. package/src/incoming-message-extensions.ts +19 -0
  265. package/src/index.ts +16 -0
  266. package/src/injector-extensions.spec.ts +19 -0
  267. package/src/injector-extensions.ts +35 -0
  268. package/src/models/cors-options.ts +21 -0
  269. package/src/models/default-session.ts +14 -0
  270. package/src/request-action-implementation.ts +70 -0
  271. package/src/rest-service.integration.spec.ts +166 -0
  272. package/src/rest.integration.test.ts +112 -0
  273. package/src/schema-validator/index.ts +2 -0
  274. package/src/schema-validator/schema-validation-error.ts +11 -0
  275. package/src/schema-validator/schema-validator.test.ts +72 -0
  276. package/src/schema-validator/schema-validator.ts +31 -0
  277. package/src/schema-validator/validate-examples.ts +38 -0
  278. package/src/server-manager.ts +88 -0
  279. package/src/server-response-extensions.spec.ts +53 -0
  280. package/src/server-response-extensions.ts +30 -0
  281. package/src/utils.ts +65 -0
  282. package/src/validate.integration.schema.ts +50 -0
  283. package/src/validate.integration.spec.schema.json +779 -0
  284. package/src/validate.integration.spec.ts +218 -0
  285. package/src/validate.ts +60 -0
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Validate = void 0;
4
+ const schema_validator_1 = require("./schema-validator");
5
+ const Validate = (validationOptions) => (action) => {
6
+ const schema = { ...validationOptions.schema };
7
+ Object.values(schema.definitions).forEach((definition) => {
8
+ var _a;
9
+ if (definition.required && definition.required.includes('result')) {
10
+ definition.required = definition.required.filter((value) => value !== 'result');
11
+ }
12
+ definition.additionalProperties = true;
13
+ if ((_a = definition.properties) === null || _a === void 0 ? void 0 : _a.headers) {
14
+ definition.properties.headers.additionalProperties = true;
15
+ }
16
+ });
17
+ const validator = new schema_validator_1.SchemaValidator(schema, { coerceTypes: true });
18
+ return async (args) => {
19
+ var _a, _b, _c;
20
+ const anyArgs = args;
21
+ let body;
22
+ const { headers } = anyArgs;
23
+ const query = (_a = anyArgs.getQuery) === null || _a === void 0 ? void 0 : _a.call(anyArgs);
24
+ const url = (_b = anyArgs.getUrlParams) === null || _b === void 0 ? void 0 : _b.call(anyArgs);
25
+ try {
26
+ body = await ((_c = anyArgs.getBody) === null || _c === void 0 ? void 0 : _c.call(anyArgs));
27
+ }
28
+ catch (error) {
29
+ // ignore
30
+ }
31
+ validator.isValid({
32
+ ...(query ? { query } : {}),
33
+ ...(body ? { body } : {}),
34
+ ...(url ? { url } : {}),
35
+ ...(headers ? { headers } : {}),
36
+ }, { schemaName: validationOptions.schemaName });
37
+ return await action({
38
+ request: args.request,
39
+ response: args.response,
40
+ injector: args.injector,
41
+ headers,
42
+ getQuery: () => query,
43
+ getUrlParams: () => url,
44
+ getBody: () => Promise.resolve(body),
45
+ });
46
+ };
47
+ };
48
+ exports.Validate = Validate;
49
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":";;;AACA,yDAAoD;AAE7C,MAAM,QAAQ,GACnB,CAAkF,iBASjF,EAAE,EAAE,CACL,CAA4B,MAAwB,EAAoB,EAAE;IACxE,MAAM,MAAM,GAAG,EAAE,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAA;IAE9C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;;QACvD,IAAI,UAAU,CAAC,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACjE,UAAU,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAA;SACrF;QACD,UAAU,CAAC,oBAAoB,GAAG,IAAI,CAAA;QACtC,IAAI,MAAA,UAAU,CAAC,UAAU,0CAAE,OAAO,EAAE;YAClC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAA;SAC1D;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG,IAAI,kCAAe,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IAEpE,OAAO,KAAK,EAAE,IAA6B,EAA4B,EAAE;;QACvE,MAAM,OAAO,GAAG,IAAW,CAAA;QAC3B,IAAI,IAAU,CAAA;QACd,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;QAC3B,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,QAAQ,+CAAhB,OAAO,CAAa,CAAA;QAClC,MAAM,GAAG,GAAG,MAAA,OAAO,CAAC,YAAY,+CAApB,OAAO,CAAiB,CAAA;QACpC,IAAI;YACF,IAAI,GAAG,MAAM,CAAA,MAAA,OAAO,CAAC,OAAO,+CAAf,OAAO,CAAY,CAAA,CAAA;SACjC;QAAC,OAAO,KAAK,EAAE;YACd,SAAS;SACV;QACD,SAAS,CAAC,OAAO,CACf;YACE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,EACD,EAAE,UAAU,EAAE,iBAAiB,CAAC,UAAU,EAAE,CAC7C,CAAA;QACD,OAAO,MAAM,MAAM,CAAC;YAClB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO;YACP,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;YACrB,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG;YACvB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;SAC9B,CAAC,CAAA;IACX,CAAC,CAAA;AACH,CAAC,CAAA;AAxDU,QAAA,QAAQ,YAwDlB"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@furystack/rest-service",
3
+ "version": "4.0.19",
4
+ "description": "Repository implementation for FuryStack",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "start:mock": "yarn node ./dist/mock.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "src"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/furystack/furystack.git"
16
+ },
17
+ "keywords": [
18
+ "FuryStack",
19
+ "HTTP",
20
+ "REST",
21
+ "API",
22
+ "Actions"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "author": "gallay.lajos@gmail.com",
28
+ "license": "GPL-2.0",
29
+ "bugs": {
30
+ "url": "https://github.com/furystack/furystack/issues"
31
+ },
32
+ "homepage": "https://github.com/furystack/furystack",
33
+ "dependencies": {
34
+ "@furystack/core": "^10.3.3",
35
+ "@furystack/inject": "^4.0.74",
36
+ "@furystack/logging": "^2.0.81",
37
+ "@furystack/repository": "^5.0.18",
38
+ "@furystack/rest": "^3.0.18",
39
+ "@furystack/utils": "^1.2.44",
40
+ "ajv": "^8.6.3",
41
+ "ajv-formats": "^2.1.1",
42
+ "hash.js": "^1.1.7",
43
+ "path-to-regexp": "^6.2.0",
44
+ "semaphore-async-await": "^1.5.1",
45
+ "tslib": "^2.3.1",
46
+ "uuid": "^8.3.2"
47
+ },
48
+ "devDependencies": {
49
+ "@types/jest": "^27.0.1",
50
+ "@types/node": "^16.9.1",
51
+ "@types/uuid": "^8.3.1",
52
+ "got": "^11.8.2"
53
+ },
54
+ "typings": "./dist/index.d.ts",
55
+ "gitHead": "0e6c724905b574603b1587fea9b6a6ed7446f93b"
56
+ }
@@ -0,0 +1,54 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { usingAsync } from '@furystack/utils'
3
+ import { ErrorAction } from './error-action'
4
+ import { IncomingMessage } from 'http'
5
+ import { RequestError } from '@furystack/rest'
6
+ import { AuthorizationError } from '@furystack/core'
7
+ import { ServerResponse } from 'http'
8
+
9
+ describe('ErrorAction tests', () => {
10
+ const request = { url: 'https://google.com' } as IncomingMessage
11
+ const response = {} as ServerResponse
12
+
13
+ it('returns the error in the standard format', async () => {
14
+ await usingAsync(new Injector(), async (i) => {
15
+ const result = await ErrorAction({
16
+ injector: i,
17
+ getBody: async () => new Error('Something went wrong'),
18
+ request,
19
+ response,
20
+ })
21
+ expect(result.statusCode).toBe(500)
22
+ expect(result.chunk.message).toBe('Something went wrong')
23
+ expect(result.chunk.url).toBe('https://google.com')
24
+ })
25
+ })
26
+
27
+ it('returns the error code from request errors', async () => {
28
+ await usingAsync(new Injector(), async (i) => {
29
+ const result = await ErrorAction({
30
+ request,
31
+ response,
32
+ injector: i,
33
+ getBody: async () => new RequestError('Something went wrong', 401),
34
+ })
35
+ expect(result.statusCode).toBe(401)
36
+ expect(result.chunk.message).toBe('Something went wrong')
37
+ expect(result.chunk.url).toBe('https://google.com')
38
+ })
39
+ })
40
+
41
+ it('returns the 403 for authorization errors', async () => {
42
+ await usingAsync(new Injector(), async (i) => {
43
+ const result = await ErrorAction({
44
+ request,
45
+ response,
46
+ injector: i,
47
+ getBody: async () => new AuthorizationError('Something went wrong'),
48
+ })
49
+ expect(result.statusCode).toBe(403)
50
+ expect(result.chunk.message).toBe('Something went wrong')
51
+ expect(result.chunk.url).toBe('https://google.com')
52
+ })
53
+ })
54
+ })
@@ -0,0 +1,34 @@
1
+ import { RequestError } from '@furystack/rest'
2
+ import { AuthorizationError } from '@furystack/core'
3
+ import { JsonResult, RequestAction } from '../request-action-implementation'
4
+ import { SchemaValidationError } from '../schema-validator'
5
+
6
+ /**
7
+ * Action for unhandled (500) errors
8
+ * Returns a serialized error instance in JSON format.
9
+ */
10
+
11
+ export const ErrorAction: RequestAction<{
12
+ body: unknown
13
+ result: { message: string; url?: string; stack?: string }
14
+ }> = async ({ getBody, request }) => {
15
+ const body = await getBody()
16
+
17
+ if (body instanceof SchemaValidationError) {
18
+ return JsonResult({ message: body.message, stack: body.stack, errors: body.errors }, 400)
19
+ }
20
+
21
+ if (body instanceof RequestError) {
22
+ return JsonResult({ message: body.message, url: request.url, stack: body.stack }, body.responseCode)
23
+ }
24
+
25
+ if (body instanceof AuthorizationError) {
26
+ return JsonResult({ message: body.message, url: request.url, stack: body.stack }, 403)
27
+ }
28
+
29
+ if (body instanceof Error) {
30
+ return JsonResult({ message: body.message, url: request.url, stack: body.stack }, 500)
31
+ }
32
+
33
+ return JsonResult({ message: 'An unexpected error happened' }, 500)
34
+ }
@@ -0,0 +1,23 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { usingAsync } from '@furystack/utils'
3
+ import { GetCurrentUser } from './get-current-user'
4
+ import { IncomingMessage, ServerResponse } from 'http'
5
+ import { IdentityContext } from '@furystack/core'
6
+
7
+ describe('getCurrentUser', () => {
8
+ const request = { url: 'https://google.com' } as IncomingMessage
9
+ const response = {} as ServerResponse
10
+
11
+ it('exec', async () => {
12
+ const testUser = { Name: 'Userke' }
13
+ await usingAsync(new Injector(), async (i) => {
14
+ i.setExplicitInstance(
15
+ { getCurrentUser: async () => testUser, isAuthenticated: async () => true },
16
+ IdentityContext,
17
+ )
18
+ const result = await GetCurrentUser({ injector: i, request, response })
19
+ expect(result.statusCode).toBe(200)
20
+ expect(result.chunk).toEqual(testUser)
21
+ })
22
+ })
23
+ })
@@ -0,0 +1,15 @@
1
+ import { User } from '@furystack/core'
2
+ import { Authenticate } from '../authenticate'
3
+ import { JsonResult, RequestAction } from '../request-action-implementation'
4
+
5
+ /**
6
+ * Action that returns the current authenticated user
7
+ *
8
+ * @param injector The injector from the current stack
9
+ */
10
+ export const GetCurrentUser: RequestAction<{
11
+ result: User
12
+ }> = Authenticate()(async ({ injector }) => {
13
+ const user = await injector.getCurrentUser()
14
+ return JsonResult(user)
15
+ })
@@ -0,0 +1,6 @@
1
+ export * from './error-action'
2
+ export * from './get-current-user'
3
+ export * from './is-authenticated'
4
+ export * from './login'
5
+ export * from './logout'
6
+ export * from './not-found-action'
@@ -0,0 +1,18 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { usingAsync } from '@furystack/utils'
3
+ import { IsAuthenticated } from './is-authenticated'
4
+ import { IncomingMessage, ServerResponse } from 'http'
5
+ import { IdentityContext } from '@furystack/core'
6
+
7
+ describe('isAuthenticated', () => {
8
+ const request = { url: 'https://google.com' } as IncomingMessage
9
+ const response = {} as ServerResponse
10
+ it('exec', async () => {
11
+ await usingAsync(new Injector(), async (i) => {
12
+ i.setExplicitInstance({ isAuthenticated: async () => true }, IdentityContext)
13
+ const result = await IsAuthenticated({ injector: i, request, response } as any)
14
+ expect(result.statusCode).toBe(200)
15
+ expect(result.chunk).toEqual({ isAuthenticated: true })
16
+ })
17
+ })
18
+ })
@@ -0,0 +1,13 @@
1
+ import { JsonResult, RequestAction } from '../request-action-implementation'
2
+
3
+ /**
4
+ * Action that returns if the current user is authenticated
5
+ *
6
+ * @param options The options for the Custom Action
7
+ * @param options.injector The Injector from the current context
8
+ * @returns A standard authentication result
9
+ */
10
+ export const IsAuthenticated: RequestAction<{ result: { isAuthenticated: boolean } }> = async ({ injector }) => {
11
+ const isAuthenticated = await injector.isAuthenticated()
12
+ return JsonResult({ isAuthenticated })
13
+ }
@@ -0,0 +1,41 @@
1
+ import { IncomingMessage, ServerResponse } from 'http'
2
+ import { Injector } from '@furystack/inject'
3
+ import { usingAsync } from '@furystack/utils'
4
+ import { LoginAction } from './login'
5
+ import { HttpUserContext } from '../http-user-context'
6
+
7
+ describe('LoginAction', () => {
8
+ const request = { url: 'https://google.com' } as IncomingMessage
9
+ const response = {} as ServerResponse
10
+
11
+ it('Returns the provided user with 200 on success', async () => {
12
+ const testUser = { Name: 'Userke' }
13
+ await usingAsync(new Injector(), async (i) => {
14
+ i.setExplicitInstance(
15
+ {
16
+ authenticateUser: jest.fn(async () => testUser),
17
+ cookieLogin: jest.fn(async () => testUser),
18
+ authentication: {},
19
+ },
20
+ HttpUserContext,
21
+ )
22
+ const result = await LoginAction({
23
+ request,
24
+ response,
25
+ injector: i,
26
+ getBody: async () => ({ username: 'testuser', password: 'alma' }),
27
+ } as any)
28
+ expect(result.chunk).toEqual(testUser)
29
+ expect(result.statusCode).toBe(200)
30
+ })
31
+ })
32
+
33
+ it('Returns throw error with 400 on fail', async () => {
34
+ await usingAsync(new Injector(), async (i) => {
35
+ i.setExplicitInstance({ cookieLogin: async () => Promise.reject(':(') }, HttpUserContext)
36
+ await expect(
37
+ LoginAction({ request, response, injector: i, getBody: async () => ({ username: '', password: '' }) }),
38
+ ).rejects.toThrowError('Login Failed')
39
+ })
40
+ })
41
+ })
@@ -0,0 +1,26 @@
1
+ import { HttpUserContext } from '../http-user-context'
2
+ import '../injector-extensions'
3
+ import { User } from '@furystack/core'
4
+ import { RequestError } from '@furystack/rest'
5
+ import { JsonResult, RequestAction } from '../request-action-implementation'
6
+
7
+ /**
8
+ * Action that logs in the current user
9
+ * Should be called with a JSON Post body with ``username`` and ``password`` fields.
10
+ * Returns the current user instance
11
+ */
12
+
13
+ export const LoginAction: RequestAction<{
14
+ result: User
15
+ body: { username: string; password: string }
16
+ }> = async ({ injector, getBody, response }) => {
17
+ const userContext = injector.getInstance(HttpUserContext)
18
+ const body = await getBody()
19
+ try {
20
+ const user = await userContext.authenticateUser(body.username, body.password)
21
+ await userContext.cookieLogin(user, response)
22
+ return JsonResult(user, 200)
23
+ } catch (error) {
24
+ throw new RequestError('Login Failed', 400)
25
+ }
26
+ }
@@ -0,0 +1,27 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { usingAsync } from '@furystack/utils'
3
+ import { HttpUserContext } from '../http-user-context'
4
+ import { LogoutAction } from './logout'
5
+ import { IncomingMessage, ServerResponse } from 'http'
6
+
7
+ describe('LogoutAction', () => {
8
+ const request = { url: 'https://google.com' } as IncomingMessage
9
+ const response = {} as ServerResponse
10
+
11
+ it('exec', async () => {
12
+ await usingAsync(new Injector(), async (i) => {
13
+ const cookieLogout = jest.fn(async () => true)
14
+ i.setExplicitInstance(
15
+ {
16
+ cookieLogout,
17
+ },
18
+ HttpUserContext,
19
+ )
20
+
21
+ const result = await LogoutAction({ request, response, injector: i } as any)
22
+ expect(result.statusCode).toBe(200)
23
+ expect(result.chunk).toBe(undefined)
24
+ expect(cookieLogout).toBeCalled()
25
+ })
26
+ })
27
+ })
@@ -0,0 +1,16 @@
1
+ import { HttpUserContext } from '../http-user-context'
2
+ import { EmptyResult, RequestAction } from '../request-action-implementation'
3
+
4
+ /**
5
+ * Action that logs out the current user
6
+ *
7
+ * @param root0 The Options object
8
+ * @param root0.injector The injector from the context
9
+ * @param root0.request The current Request object
10
+ * @param root0.response The Response object
11
+ * @returns An empty result that indicates the success
12
+ */
13
+ export const LogoutAction: RequestAction<{ result: unknown }> = async ({ injector, request, response }) => {
14
+ await injector.getInstance(HttpUserContext).cookieLogout(request, response)
15
+ return EmptyResult()
16
+ }
@@ -0,0 +1,17 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { usingAsync } from '@furystack/utils'
3
+ import { NotFoundAction } from './not-found-action'
4
+ import { IncomingMessage, ServerResponse } from 'http'
5
+
6
+ describe('NotFoundAction tests', () => {
7
+ const request = { url: 'https://google.com' } as IncomingMessage
8
+ const response = {} as ServerResponse
9
+
10
+ it('exec', async () => {
11
+ await usingAsync(new Injector(), async (i) => {
12
+ const result = await NotFoundAction({ injector: i, request, response })
13
+ expect(result.statusCode).toBe(404)
14
+ expect(result.chunk).toEqual({ error: 'Content not found' })
15
+ })
16
+ })
17
+ })
@@ -0,0 +1,13 @@
1
+ import { JsonResult, RequestAction } from '../request-action-implementation'
2
+
3
+ /**
4
+ * @returns The standard Not Found action result
5
+ */
6
+ export const NotFoundAction: RequestAction<{ result: { error: string } }> = async () => {
7
+ return JsonResult(
8
+ {
9
+ error: 'Content not found',
10
+ },
11
+ 404,
12
+ )
13
+ }
@@ -0,0 +1,133 @@
1
+ import { IncomingMessage, ServerResponse } from 'http'
2
+ import { Utils } from './utils'
3
+
4
+ describe('AddCorsHeaders', () => {
5
+ const utils = new Utils()
6
+ it('Should NOT add headers for non-cross-site requests', () => {
7
+ const req: IncomingMessage = {
8
+ headers: { origin: 'http://localhost/', host: 'http://localhost' },
9
+ } as any as IncomingMessage
10
+ const resp: ServerResponse = {
11
+ setHeader: jest.fn(),
12
+ } as unknown as ServerResponse
13
+
14
+ utils.addCorsHeaders(
15
+ {
16
+ origins: ['https://google.com'],
17
+ credentials: true,
18
+ headers: ['my-custom-header', 'header-2'],
19
+ },
20
+ req,
21
+ resp,
22
+ )
23
+ expect(resp.setHeader).not.toBeCalled()
24
+ })
25
+
26
+ it('Should NOT add headers for not-enabled hosts', () => {
27
+ const req: IncomingMessage = {
28
+ headers: { origin: 'http://localhost/', host: 'http://google.com' },
29
+ } as any as IncomingMessage
30
+ const resp: ServerResponse = {
31
+ setHeader: jest.fn(),
32
+ } as unknown as ServerResponse
33
+
34
+ utils.addCorsHeaders(
35
+ {
36
+ origins: ['https://github.com'],
37
+ credentials: true,
38
+ headers: ['my-custom-header', 'header-2'],
39
+ },
40
+ req,
41
+ resp,
42
+ )
43
+ expect(resp.setHeader).not.toBeCalled()
44
+ })
45
+
46
+ it('Should add allow-origin header for enabled hosts', () => {
47
+ const req: IncomingMessage = {
48
+ headers: { origin: 'http://localhost/', host: 'http://github.com' },
49
+ } as any as IncomingMessage
50
+ const resp: ServerResponse = {
51
+ setHeader: jest.fn(),
52
+ } as unknown as ServerResponse
53
+
54
+ utils.addCorsHeaders(
55
+ {
56
+ origins: ['http://localhost/'],
57
+ },
58
+ req,
59
+ resp,
60
+ )
61
+ expect(resp.setHeader).toBeCalledTimes(1)
62
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Origin', 'http://localhost/')
63
+ })
64
+
65
+ it('Should add allow-credentials header if enabled', () => {
66
+ const req: IncomingMessage = {
67
+ headers: { origin: 'http://localhost/', host: 'http://github.com' },
68
+ } as any as IncomingMessage
69
+ const resp: ServerResponse = {
70
+ setHeader: jest.fn(),
71
+ } as unknown as ServerResponse
72
+
73
+ utils.addCorsHeaders(
74
+ {
75
+ origins: ['http://localhost/'],
76
+ credentials: true,
77
+ // headers: ['my-custom-header', 'header-2'],
78
+ // methods: ['DELETE', 'GET', 'POST', 'PUT', 'PATCH'],
79
+ },
80
+ req,
81
+ resp,
82
+ )
83
+ expect(resp.setHeader).toBeCalledTimes(2)
84
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Origin', 'http://localhost/')
85
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Credentials', 'true')
86
+ // expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Headers', 'my-custom-header, header-2')
87
+ // expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Methods', 'DELETE, GET, POST, PUT, PATCH')
88
+ })
89
+
90
+ it('Should add allow-headers header if enabled', () => {
91
+ const req: IncomingMessage = {
92
+ headers: { origin: 'http://localhost/', host: 'http://github.com' },
93
+ } as any as IncomingMessage
94
+ const resp: ServerResponse = {
95
+ setHeader: jest.fn(),
96
+ } as unknown as ServerResponse
97
+
98
+ utils.addCorsHeaders(
99
+ {
100
+ origins: ['http://localhost/'],
101
+ headers: ['my-custom-header', 'header-2'],
102
+ // methods: ['DELETE', 'GET', 'POST', 'PUT', 'PATCH'],
103
+ },
104
+ req,
105
+ resp,
106
+ )
107
+ expect(resp.setHeader).toBeCalledTimes(2)
108
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Origin', 'http://localhost/')
109
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Headers', 'my-custom-header, header-2')
110
+ // expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Methods', 'DELETE, GET, POST, PUT, PATCH')
111
+ })
112
+
113
+ it('Should add allow-methods header if enabled', () => {
114
+ const req: IncomingMessage = {
115
+ headers: { origin: 'http://localhost/', host: 'http://github.com' },
116
+ } as any as IncomingMessage
117
+ const resp: ServerResponse = {
118
+ setHeader: jest.fn(),
119
+ } as unknown as ServerResponse
120
+
121
+ utils.addCorsHeaders(
122
+ {
123
+ origins: ['http://localhost/'],
124
+ methods: ['DELETE', 'GET', 'POST', 'PUT', 'PATCH'],
125
+ },
126
+ req,
127
+ resp,
128
+ )
129
+ expect(resp.setHeader).toBeCalledTimes(2)
130
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Origin', 'http://localhost/')
131
+ expect(resp.setHeader).toBeCalledWith('Access-Control-Allow-Methods', 'DELETE, GET, POST, PUT, PATCH')
132
+ })
133
+ })