@intellegens/cornerstone-client 0.0.9999-alpha-8 → 0.0.9999-alpha-10

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 (227) hide show
  1. package/demo/index.ts +29 -0
  2. package/demo/public_html/favicon.ico +0 -0
  3. package/demo/public_html/index.html +106 -0
  4. package/demo/public_html/websettings.json +3 -0
  5. package/{adapters → dist/adapters}/CollectionViewAdapter/index.d.ts +0 -0
  6. package/{adapters → dist/adapters}/CollectionViewAdapter/index.js +0 -0
  7. package/{adapters → dist/adapters}/index.d.ts +0 -0
  8. package/{adapters → dist/adapters}/index.js +0 -0
  9. package/{data → dist/data}/api/dto/PropertyPathDto.d.ts +0 -0
  10. package/{data → dist/data}/api/dto/PropertyPathDto.js +0 -0
  11. package/{data → dist/data}/api/dto/ReadOptionsDto.d.ts +0 -0
  12. package/{data → dist/data}/api/dto/ReadOptionsDto.js +0 -0
  13. package/{data → dist/data}/api/dto/ReadResultDto.d.ts +0 -0
  14. package/{data → dist/data}/api/dto/ReadResultDto.js +0 -0
  15. package/{data → dist/data}/api/dto/ReadResultMetadataDto.d.ts +0 -0
  16. package/{data → dist/data}/api/dto/ReadResultMetadataDto.js +0 -0
  17. package/{data → dist/data}/api/dto/crud/CrudMetadataDto.d.ts +0 -0
  18. package/{data → dist/data}/api/dto/crud/CrudMetadataDto.js +0 -0
  19. package/{data → dist/data}/api/dto/crud/index.d.ts +0 -0
  20. package/{data → dist/data}/api/dto/crud/index.js +0 -0
  21. package/{data → dist/data}/api/dto/index.d.ts +0 -0
  22. package/{data → dist/data}/api/dto/index.js +0 -0
  23. package/{data → dist/data}/api/dto/read/ReadMetadataDto.d.ts +0 -0
  24. package/{data → dist/data}/api/dto/read/ReadMetadataDto.js +0 -0
  25. package/{data → dist/data}/api/dto/read/ReadSelectedDefinitionDto.d.ts +0 -0
  26. package/{data → dist/data}/api/dto/read/ReadSelectedDefinitionDto.js +0 -0
  27. package/{data → dist/data}/api/dto/read/ReadSelectedOrderingDefinitionDto.d.ts +0 -0
  28. package/{data → dist/data}/api/dto/read/ReadSelectedOrderingDefinitionDto.js +0 -0
  29. package/{data → dist/data}/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.d.ts +0 -0
  30. package/{data → dist/data}/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.js +0 -0
  31. package/{data → dist/data}/api/dto/read/ReadSelectedPaginationDefinitionDto.d.ts +0 -0
  32. package/{data → dist/data}/api/dto/read/ReadSelectedPaginationDefinitionDto.js +0 -0
  33. package/{data → dist/data}/api/dto/read/ReadSelectedSearchDefinitionDto.d.ts +0 -0
  34. package/{data → dist/data}/api/dto/read/ReadSelectedSearchDefinitionDto.js +0 -0
  35. package/{data → dist/data}/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.d.ts +0 -0
  36. package/{data → dist/data}/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.js +0 -0
  37. package/{data → dist/data}/api/dto/read/index.d.ts +0 -0
  38. package/{data → dist/data}/api/dto/read/index.js +0 -0
  39. package/{data → dist/data}/api/dto/response/ApiErrorDto.d.ts +0 -0
  40. package/{data → dist/data}/api/dto/response/ApiErrorDto.js +0 -0
  41. package/{data → dist/data}/api/dto/response/ApiResponseDto.d.ts +0 -0
  42. package/{data → dist/data}/api/dto/response/ApiResponseDto.js +0 -0
  43. package/{data → dist/data}/api/dto/response/ApiSuccessResponseDto.d.ts +0 -0
  44. package/{data → dist/data}/api/dto/response/ApiSuccessResponseDto.js +0 -0
  45. package/{data → dist/data}/api/dto/response/EmptyMetadataDto.d.ts +0 -0
  46. package/{data → dist/data}/api/dto/response/EmptyMetadataDto.js +0 -0
  47. package/{data → dist/data}/api/dto/response/index.d.ts +0 -0
  48. package/{data → dist/data}/api/dto/response/index.js +0 -0
  49. package/{data → dist/data}/api/enum/index.d.ts +0 -0
  50. package/{data → dist/data}/api/enum/index.js +0 -0
  51. package/{data → dist/data}/api/enum/read/ReadSelectedComparisonOperator.d.ts +0 -0
  52. package/{data → dist/data}/api/enum/read/ReadSelectedComparisonOperator.js +0 -0
  53. package/{data → dist/data}/api/enum/read/ReadSelectedLogicalOperator.d.ts +0 -0
  54. package/{data → dist/data}/api/enum/read/ReadSelectedLogicalOperator.js +0 -0
  55. package/{data → dist/data}/api/enum/read/ReadSelectedOrderingDirection.d.ts +0 -0
  56. package/{data → dist/data}/api/enum/read/ReadSelectedOrderingDirection.js +0 -0
  57. package/{data → dist/data}/api/enum/read/ReadSelectedPropertyType.d.ts +0 -0
  58. package/{data → dist/data}/api/enum/read/ReadSelectedPropertyType.js +0 -0
  59. package/{data → dist/data}/api/enum/read/index.d.ts +0 -0
  60. package/{data → dist/data}/api/enum/read/index.js +0 -0
  61. package/{data → dist/data}/api/enum/response/ApiErrorCodes.d.ts +0 -0
  62. package/{data → dist/data}/api/enum/response/ApiErrorCodes.js +0 -0
  63. package/{data → dist/data}/api/enum/response/index.d.ts +0 -0
  64. package/{data → dist/data}/api/enum/response/index.js +0 -0
  65. package/{data → dist/data}/api/index.d.ts +0 -0
  66. package/{data → dist/data}/api/index.js +0 -0
  67. package/{data → dist/data}/api/interface/IConcurrencySafe.d.ts +0 -0
  68. package/{data → dist/data}/api/interface/IConcurrencySafe.js +0 -0
  69. package/{data → dist/data}/api/interface/IIdentifiable.d.ts +0 -0
  70. package/{data → dist/data}/api/interface/IIdentifiable.js +0 -0
  71. package/{data → dist/data}/api/interface/IIdentifiableSecondary.d.ts +0 -0
  72. package/{data → dist/data}/api/interface/IIdentifiableSecondary.js +0 -0
  73. package/{data → dist/data}/api/interface/index.d.ts +0 -0
  74. package/{data → dist/data}/api/interface/index.js +0 -0
  75. package/{data → dist/data}/auth/dto/ClaimDto.d.ts +0 -0
  76. package/{data → dist/data}/auth/dto/ClaimDto.js +0 -0
  77. package/{data → dist/data}/auth/dto/RegisterRequestDto.d.ts +0 -0
  78. package/{data → dist/data}/auth/dto/RegisterRequestDto.js +0 -0
  79. package/{data → dist/data}/auth/dto/RoleDto.d.ts +0 -0
  80. package/{data → dist/data}/auth/dto/RoleDto.js +0 -0
  81. package/{data → dist/data}/auth/dto/SignInRequestDto.d.ts +0 -0
  82. package/{data → dist/data}/auth/dto/SignInRequestDto.js +0 -0
  83. package/{data → dist/data}/auth/dto/TokensDto.d.ts +0 -0
  84. package/{data → dist/data}/auth/dto/TokensDto.js +0 -0
  85. package/{data → dist/data}/auth/dto/UserDto.d.ts +0 -0
  86. package/{data → dist/data}/auth/dto/UserDto.js +0 -0
  87. package/{data → dist/data}/auth/dto/UserInfoDto.d.ts +0 -0
  88. package/{data → dist/data}/auth/dto/UserInfoDto.js +0 -0
  89. package/{data → dist/data}/auth/dto/index.d.ts +0 -0
  90. package/{data → dist/data}/auth/dto/index.js +0 -0
  91. package/{data → dist/data}/auth/index.d.ts +0 -0
  92. package/{data → dist/data}/auth/index.js +0 -0
  93. package/{data → dist/data}/index.d.ts +0 -0
  94. package/{data → dist/data}/index.js +0 -0
  95. package/{index.d.ts → dist/index.d.ts} +0 -0
  96. package/{index.js → dist/index.js} +0 -0
  97. package/{services → dist/services}/api/ApiCrudControllerClient/index.d.ts +0 -0
  98. package/{services → dist/services}/api/ApiCrudControllerClient/index.js +0 -0
  99. package/{services → dist/services}/api/ApiInitializationService/index.d.ts +0 -0
  100. package/{services → dist/services}/api/ApiInitializationService/index.js +0 -0
  101. package/{services → dist/services}/api/ApiReadControllerClient/index.d.ts +0 -0
  102. package/{services → dist/services}/api/ApiReadControllerClient/index.js +0 -0
  103. package/{services → dist/services}/api/HttpService/FetchHttpService.d.ts +0 -0
  104. package/{services → dist/services}/api/HttpService/FetchHttpService.js +0 -0
  105. package/{services → dist/services}/api/HttpService/HttpRequestConfig.d.ts +0 -0
  106. package/{services → dist/services}/api/HttpService/HttpRequestConfig.js +0 -0
  107. package/{services → dist/services}/api/HttpService/HttpResponse.d.ts +0 -0
  108. package/{services → dist/services}/api/HttpService/HttpResponse.js +0 -0
  109. package/{services → dist/services}/api/HttpService/IHttpService.d.ts +0 -0
  110. package/{services → dist/services}/api/HttpService/IHttpService.js +0 -0
  111. package/{services → dist/services}/api/HttpService/index.d.ts +0 -0
  112. package/{services → dist/services}/api/HttpService/index.js +0 -0
  113. package/{services → dist/services}/api/UserManagementControllerClient/index.d.ts +0 -0
  114. package/{services → dist/services}/api/UserManagementControllerClient/index.js +0 -0
  115. package/{services → dist/services}/api/index.d.ts +0 -0
  116. package/{services → dist/services}/api/index.js +0 -0
  117. package/{services → dist/services}/auth/client/AuthService/index.d.ts +0 -0
  118. package/{services → dist/services}/auth/client/AuthService/index.js +0 -0
  119. package/{services → dist/services}/auth/client/AuthorizationManagementControllerClient/index.d.ts +0 -0
  120. package/{services → dist/services}/auth/client/AuthorizationManagementControllerClient/index.js +0 -0
  121. package/{services → dist/services}/auth/client/index.d.ts +0 -0
  122. package/{services → dist/services}/auth/client/index.js +0 -0
  123. package/{services → dist/services}/auth/index.d.ts +0 -0
  124. package/{services → dist/services}/auth/index.js +0 -0
  125. package/{services → dist/services}/index.d.ts +0 -0
  126. package/{services → dist/services}/index.js +0 -0
  127. package/{utils → dist/utils}/index.d.ts +0 -0
  128. package/{utils → dist/utils}/index.js +0 -0
  129. package/jest.config.js +29 -0
  130. package/package.json +24 -24
  131. package/src/adapters/CollectionViewAdapter/index.ts +390 -0
  132. package/src/adapters/index.ts +1 -0
  133. package/src/data/api/dto/PropertyPathDto.ts +4 -0
  134. package/src/data/api/dto/ReadOptionsDto.ts +8 -0
  135. package/src/data/api/dto/ReadResultDto.ts +13 -0
  136. package/src/data/api/dto/ReadResultMetadataDto.ts +8 -0
  137. package/src/data/api/dto/crud/CrudMetadataDto.ts +4 -0
  138. package/src/data/api/dto/crud/index.ts +1 -0
  139. package/src/data/api/dto/index.ts +4 -0
  140. package/src/data/api/dto/read/ReadMetadataDto.ts +8 -0
  141. package/src/data/api/dto/read/ReadSelectedDefinitionDto.ts +21 -0
  142. package/src/data/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.ts +25 -0
  143. package/src/data/api/dto/read/ReadSelectedNestedCriteriaDto.ts +20 -0
  144. package/src/data/api/dto/read/ReadSelectedOrderingDefinitionDto.ts +8 -0
  145. package/src/data/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.ts +16 -0
  146. package/src/data/api/dto/read/ReadSelectedPaginationDefinitionDto.ts +13 -0
  147. package/src/data/api/dto/read/ReadSelectedSearchDefinitionDto.ts +43 -0
  148. package/src/data/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.ts +186 -0
  149. package/src/data/api/dto/read/index.ts +9 -0
  150. package/src/data/api/dto/response/ApiErrorDto.ts +21 -0
  151. package/src/data/api/dto/response/ApiErrorResponseDto.ts +13 -0
  152. package/src/data/api/dto/response/ApiResponseDto.ts +7 -0
  153. package/src/data/api/dto/response/ApiSuccessResponseDto.ts +13 -0
  154. package/src/data/api/dto/response/MetadataDto.ts +24 -0
  155. package/src/data/api/dto/response/index.ts +5 -0
  156. package/src/data/api/enum/index.ts +2 -0
  157. package/src/data/api/enum/read/ReadSelectedCollectionOperator.ts +17 -0
  158. package/src/data/api/enum/read/ReadSelectedComparisonOperator.ts +96 -0
  159. package/src/data/api/enum/read/ReadSelectedLogicalOperator.ts +16 -0
  160. package/src/data/api/enum/read/ReadSelectedOrderingDirection.ts +13 -0
  161. package/src/data/api/enum/read/ReadSelectedPropertyType.ts +86 -0
  162. package/src/data/api/enum/read/index.ts +5 -0
  163. package/src/data/api/enum/response/ErrorCode.ts +13 -0
  164. package/src/data/api/enum/response/index.ts +1 -0
  165. package/src/data/api/index.ts +3 -0
  166. package/src/data/api/interface/IConcurrencySafe.ts +9 -0
  167. package/src/data/api/interface/IIdentifiable.ts +12 -0
  168. package/src/data/api/interface/IIdentifiableSecondary.ts +9 -0
  169. package/src/data/api/interface/index.ts +3 -0
  170. package/src/data/auth/dto/ClaimDto.ts +4 -0
  171. package/src/data/auth/dto/RegisterRequestDto.ts +4 -0
  172. package/src/data/auth/dto/RoleDto.ts +6 -0
  173. package/src/data/auth/dto/SignInRequestDto.ts +4 -0
  174. package/src/data/auth/dto/TokensDto.ts +4 -0
  175. package/src/data/auth/dto/UserDto.ts +18 -0
  176. package/src/data/auth/dto/UserInfoDto.ts +15 -0
  177. package/src/data/auth/dto/index.ts +4 -0
  178. package/src/data/auth/index.ts +2 -0
  179. package/src/data/auth/policy.ts +63 -0
  180. package/src/data/index.ts +2 -0
  181. package/src/index.ts +4 -0
  182. package/src/services/api/ApiCrudControllerClient/index.ts +129 -0
  183. package/src/services/api/ApiInitializationService/index.ts +254 -0
  184. package/src/services/api/ApiReadControllerClient/index.ts +137 -0
  185. package/src/services/api/HttpService/FetchHttpService.ts +34 -0
  186. package/src/services/api/HttpService/HttpRequestConfig.ts +10 -0
  187. package/src/services/api/HttpService/HttpResponse.ts +14 -0
  188. package/src/services/api/HttpService/IHttpService.ts +17 -0
  189. package/src/services/api/HttpService/README.md +106 -0
  190. package/src/services/api/HttpService/index.ts +12 -0
  191. package/src/services/api/UserManagementControllerClient/index.ts +160 -0
  192. package/src/services/api/index.ts +5 -0
  193. package/src/services/auth/client/AuthService/index.ts +187 -0
  194. package/src/services/auth/client/AuthorizationManagementControllerClient/index.ts +165 -0
  195. package/src/services/auth/client/index.ts +2 -0
  196. package/src/services/auth/index.ts +1 -0
  197. package/src/services/index.ts +2 -0
  198. package/src/utils/authorization/index.ts +47 -0
  199. package/src/utils/index.ts +2 -0
  200. package/src/utils/result/index.ts +25 -0
  201. package/src/utils/search/index.ts +150 -0
  202. package/tests/ApiClients.test.ts +284 -0
  203. package/tests/CollectionViewAdapter.test.ts +392 -0
  204. package/tests/HttpService.test.ts +303 -0
  205. package/tests/setup.ts +76 -0
  206. package/tsconfig.json +19 -0
  207. package/LICENSE.md +0 -7
  208. /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.d.ts +0 -0
  209. /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.js +0 -0
  210. /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCriteriaDto.d.ts +0 -0
  211. /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCriteriaDto.js +0 -0
  212. /package/{data → dist/data}/api/dto/response/ApiErrorResponseDto.d.ts +0 -0
  213. /package/{data → dist/data}/api/dto/response/ApiErrorResponseDto.js +0 -0
  214. /package/{data → dist/data}/api/dto/response/MetadataDto.d.ts +0 -0
  215. /package/{data → dist/data}/api/dto/response/MetadataDto.js +0 -0
  216. /package/{data → dist/data}/api/enum/read/ReadSelectedCollectionOperator.d.ts +0 -0
  217. /package/{data → dist/data}/api/enum/read/ReadSelectedCollectionOperator.js +0 -0
  218. /package/{data → dist/data}/api/enum/response/ErrorCode.d.ts +0 -0
  219. /package/{data → dist/data}/api/enum/response/ErrorCode.js +0 -0
  220. /package/{data → dist/data}/auth/policy.d.ts +0 -0
  221. /package/{data → dist/data}/auth/policy.js +0 -0
  222. /package/{utils → dist/utils}/authorization/index.d.ts +0 -0
  223. /package/{utils → dist/utils}/authorization/index.js +0 -0
  224. /package/{utils → dist/utils}/result/index.d.ts +0 -0
  225. /package/{utils → dist/utils}/result/index.js +0 -0
  226. /package/{utils → dist/utils}/search/index.d.ts +0 -0
  227. /package/{utils → dist/utils}/search/index.js +0 -0
@@ -0,0 +1,106 @@
1
+ # HTTP Service Abstraction
2
+
3
+ This module provides an abstraction layer for HTTP requests, allowing you to plug in different HTTP client implementations (Fetch API, Angular HttpClient, etc.) while maintaining the same interface.
4
+
5
+ ## Overview
6
+
7
+ The HTTP service abstraction consists of:
8
+
9
+ - `IHttpService` - Interface that all HTTP implementations must follow
10
+ - `FetchHttpService` - Default implementation using the Fetch API
11
+ - `AngularHttpService` - Implementation using Angular's HttpClient
12
+
13
+ ## Usage
14
+
15
+ ### Using the Default Fetch Implementation
16
+
17
+ ```typescript
18
+ import { ApiReadControllerClient, defaultHttpService } from '@services';
19
+
20
+ // Uses FetchHttpService by default
21
+ const client = new ApiReadControllerClient('/api/users');
22
+
23
+ // Or explicitly pass the default service
24
+ const client2 = new ApiReadControllerClient('/api/users', defaultHttpService);
25
+ ```
26
+
27
+ ### Using Angular HttpClient Implementation
28
+
29
+ ```typescript
30
+ import { inject } from '@angular/core';
31
+ import { HttpClient } from '@angular/common/http';
32
+ import { ApiReadControllerClient, AngularHttpService } from '@services';
33
+
34
+ const httpClient = inject<HttpClient>();
35
+ const angularHttpService = new AngularHttpService(httpClient);
36
+
37
+ // Set Angular HTTP service globaly
38
+ await apiInitializationService.initialize({ httpService: angularHttpService });
39
+ // Or for an explicitly chosen client
40
+ const apiClient = new ApiReadControllerClient('/api/users', angularHttpService);
41
+ ```
42
+
43
+ > **📦 For complete Angular integration guide, see [@intellegens/cornerstone-client-angular README](../../../../..//angular/README.md)**
44
+
45
+ ## Creating Custom HTTP Service
46
+
47
+ You can create your own HTTP service implementation by implementing the `IHttpService` interface:
48
+
49
+ ```typescript
50
+ import { IHttpService, HttpRequestConfig, HttpResponse } from '@services';
51
+
52
+ export class CustomHttpService implements IHttpService {
53
+ async request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
54
+ // Your custom HTTP implementation here
55
+ const response = await yourCustomHttpClient.request({
56
+ url,
57
+ method: config?.method || 'GET',
58
+ headers: config?.headers,
59
+ data: config?.body,
60
+ withCredentials: config?.credentials === 'include',
61
+ });
62
+
63
+ return {
64
+ ok: response.status >= 200 && response.status < 300,
65
+ status: response.status,
66
+ statusText: response.statusText,
67
+ headers: response.headers,
68
+ json: async () => response.data,
69
+ text: async () => JSON.stringify(response.data),
70
+ };
71
+ }
72
+ }
73
+ ```
74
+
75
+ ## API Reference
76
+
77
+ ### IHttpService Interface
78
+
79
+ ```typescript
80
+ interface IHttpService {
81
+ request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
82
+ }
83
+ ```
84
+
85
+ ### HttpRequestConfig Interface
86
+
87
+ ```typescript
88
+ interface HttpRequestConfig {
89
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
90
+ headers?: Record<string, string>;
91
+ body?: string;
92
+ credentials?: RequestCredentials;
93
+ }
94
+ ```
95
+
96
+ ### HttpResponse Interface
97
+
98
+ ```typescript
99
+ interface HttpResponse<T = any> {
100
+ ok: boolean;
101
+ status: number;
102
+ statusText: string;
103
+ headers: Record<string, string>;
104
+ json(): Promise<T>;
105
+ text(): Promise<string>;
106
+ }
@@ -0,0 +1,12 @@
1
+ import { FetchHttpService } from './FetchHttpService';
2
+
3
+ /**
4
+ * Default HTTP service instance
5
+ */
6
+ export const defaultHttpService = new FetchHttpService();
7
+
8
+ // Export additional HTTP service implementations
9
+ export * from './FetchHttpService';
10
+ export * from './HttpRequestConfig';
11
+ export * from './HttpResponse';
12
+ export * from './IHttpService';
@@ -0,0 +1,160 @@
1
+ import { ApiCrudControllerClient } from '../ApiCrudControllerClient';
2
+ import { apiInitializationService } from '../ApiInitializationService';
3
+ import { IHttpService } from '../HttpService';
4
+ import { ApiErrorResponseDto, ApiResponseDto, ApiSuccessResponseDto, ClaimDto, EmptyMetadataDto, ErrorCode, ReadMetadataDto, UserDto } from '@data';
5
+ import { fail, ok } from '@utils/result';
6
+
7
+ /**
8
+ * Client for user management operations
9
+ *
10
+ * @export
11
+ * @class UserManagementControllerClient
12
+ * @template TKey - Type of the entity key (e.g., number, string, GUID, etc.)
13
+ * @template TUser - Data Transfer Object representing the user entity
14
+ */
15
+ export class UserManagementControllerClient<TKey, TUser extends UserDto<TKey>> extends ApiCrudControllerClient<TKey, TUser> {
16
+ /**
17
+ * Constructor
18
+ * @param baseControllerPath Base path to API controller
19
+ * @param httpService HTTP service implementation to use for requests
20
+ */
21
+ constructor(baseControllerPath: string, httpService?: IHttpService) {
22
+ super(baseControllerPath, httpService);
23
+ }
24
+
25
+ /**
26
+ * Gets the roles assigned to a user
27
+ * @param id - The ID of the user
28
+ * @param {AbortSignal} [signal] - Optional cancellation signal
29
+ * @returns List of role names assigned to the user
30
+ */
31
+ public async getUserRoles(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<string[], ReadMetadataDto>> {
32
+ try {
33
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetUserRoles', encodeURIComponent(String(id)));
34
+ const res = await this.httpService.request(url, {
35
+ method: 'GET',
36
+ credentials: 'include',
37
+ signal,
38
+ });
39
+
40
+ if (!res.ok) {
41
+ return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
42
+ }
43
+
44
+ return ok<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
45
+ } catch (err) {
46
+ console.error(err);
47
+
48
+ return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>({
49
+ error: {
50
+ code: ErrorCode.UnknownError,
51
+ message: 'Unknown error while fetching user roles',
52
+ metadata: {} as EmptyMetadataDto,
53
+ },
54
+ });
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Gets the claims assigned to a user
60
+ * @param id - The ID of the user
61
+ * @param {AbortSignal} [signal] - Optional cancellation signal
62
+ * @returns List of claims assigned to the user
63
+ */
64
+ public async getUserClaims(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<ClaimDto[], ReadMetadataDto>> {
65
+ try {
66
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetUserClaims', encodeURIComponent(String(id)));
67
+ const res = await this.httpService.request(url, {
68
+ method: 'GET',
69
+ credentials: 'include',
70
+ signal,
71
+ });
72
+
73
+ if (!res.ok) {
74
+ return fail<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
75
+ }
76
+
77
+ return ok<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
78
+ } catch (err) {
79
+ console.error(err);
80
+
81
+ return fail<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>({
82
+ error: {
83
+ code: ErrorCode.UnknownError,
84
+ message: 'Unknown error while fetching user claims',
85
+ metadata: {} as EmptyMetadataDto,
86
+ },
87
+ });
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Gets all available roles in the system
93
+ * @param {AbortSignal} [signal] - Optional cancellation signal
94
+ * @returns List of all role names
95
+ */
96
+ public async getAllRoles(signal?: AbortSignal): Promise<ApiResponseDto<string[], ReadMetadataDto>> {
97
+ try {
98
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetAllRoles');
99
+ const res = await this.httpService.request(url, {
100
+ method: 'GET',
101
+ credentials: 'include',
102
+ signal,
103
+ });
104
+
105
+ if (!res.ok) {
106
+ return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
107
+ }
108
+
109
+ return ok<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
110
+ } catch (err) {
111
+ console.error(err);
112
+
113
+ return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>({
114
+ error: {
115
+ code: ErrorCode.UnknownError,
116
+ message: 'Unknown error while fetching all roles',
117
+ metadata: {} as EmptyMetadataDto,
118
+ },
119
+ });
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Changes the password for a user
125
+ * @param id - The ID of the user
126
+ * @param newPassword - The new password to set
127
+ * @param {AbortSignal} [signal] - Optional cancellation signal
128
+ * @returns Promise that resolves when the password is changed successfully
129
+ */
130
+ public async changePassword(id: TKey, newPassword: string, signal?: AbortSignal): Promise<ApiResponseDto<undefined, EmptyMetadataDto>> {
131
+ try {
132
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'ChangePassword', encodeURIComponent(String(id)));
133
+ const res = await this.httpService.request(url, {
134
+ method: 'POST',
135
+ headers: {
136
+ 'Content-Type': 'application/json',
137
+ },
138
+ body: JSON.stringify(newPassword),
139
+ credentials: 'include',
140
+ signal,
141
+ });
142
+
143
+ if (!res.ok) {
144
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
145
+ }
146
+
147
+ return ok<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(undefined);
148
+ } catch (err) {
149
+ console.error(err);
150
+
151
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>({
152
+ error: {
153
+ code: ErrorCode.UnknownError,
154
+ message: 'Unknown error while changing password',
155
+ metadata: {} as EmptyMetadataDto,
156
+ },
157
+ });
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,5 @@
1
+ export * from './HttpService';
2
+ export * from './ApiInitializationService';
3
+ export * from './ApiReadControllerClient';
4
+ export * from './ApiCrudControllerClient';
5
+ export * from './UserManagementControllerClient';
@@ -0,0 +1,187 @@
1
+ import { apiInitializationService, IHttpService } from '@services';
2
+ import { ApiErrorResponseDto, ApiResponseDto, ApiSuccessResponseDto, EmptyMetadataDto, ErrorCode, IPolicy, PolicyBase, UserDto, UserInfoDto } from '@data';
3
+ import { fail, ok } from '@utils';
4
+
5
+ export { UserDto, UserInfoDto };
6
+
7
+ /**
8
+ * AuthService class is responsible for managing user authentication operations.
9
+ * It supports login, logout, and checking the current user's details.
10
+ *
11
+ * @export
12
+ * @class AuthService
13
+ */
14
+ export class AuthService<TKey, TUser extends UserDto<TKey> = UserDto<TKey>> {
15
+ /**
16
+ * Constructor
17
+ * @param baseControllerPath Base path to Auth API controller
18
+ * @param httpService HTTP service implementation to use for requests
19
+ */
20
+ constructor(
21
+ protected readonly baseControllerPath: string = 'Auth',
22
+ httpService?: IHttpService,
23
+ ) {
24
+ this._httpService = httpService;
25
+ }
26
+
27
+ // #region HTTP service
28
+ private readonly _httpService?: IHttpService = undefined;
29
+
30
+ /**
31
+ * Gets globally selected HTTP service
32
+ */
33
+ protected get httpService(): IHttpService {
34
+ return this._httpService || apiInitializationService._getHttpService();
35
+ }
36
+
37
+ // #endregion
38
+
39
+ /**
40
+ * Holds currently authenticated user's details
41
+ */
42
+ public user: TUser | undefined = undefined;
43
+
44
+ /**
45
+ * Initializes the Authentication status by checking with the API if the current user is authenticated or not
46
+ *
47
+ * @async
48
+ * @return {Promise<void>} Resolves when initialization is complete.
49
+ */
50
+ public async initialize(): Promise<void> {
51
+ // Check user's authentication status
52
+ await this.whoAmI();
53
+ }
54
+
55
+ /**
56
+ * Checks if user is authenticated and retrieves the current user's details if they are
57
+ *
58
+ * @return {Promise<UserInfoDto<TKey, TUser>>} Currently logged in user's details
59
+ * @throws {Error} Error if fetch fails
60
+ */
61
+ public async whoAmI(): Promise<ApiResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>> {
62
+ try {
63
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/whoami');
64
+ const res = await this.httpService.request(url, { credentials: 'include' });
65
+
66
+ if (!res.ok) {
67
+ this.user = undefined;
68
+ return fail<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
69
+ }
70
+
71
+ const response = ok<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
72
+
73
+ if (!response.ok) {
74
+ this.user = undefined;
75
+ return response;
76
+ }
77
+
78
+ this.user = response.result.user;
79
+
80
+ return response;
81
+ } catch (err) {
82
+ console.error(err);
83
+
84
+ return fail<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>({
85
+ error: {
86
+ code: ErrorCode.UnknownError,
87
+ message: 'Failed checking authentication status',
88
+ metadata: {} as EmptyMetadataDto,
89
+ },
90
+ });
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Authenticates a user using their username and password, and retrieves user's details
96
+ *
97
+ * @param {string} username Login credentials: username
98
+ * @param {string} password Login credentials: password
99
+ * @return {Promise<TUser>} Currently logged in user's details
100
+ * @throws {Error} Error if fetch fails
101
+ */
102
+ public async signIn(username: string, password: string): Promise<ApiResponseDto<TUser, EmptyMetadataDto>> {
103
+ try {
104
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/signin');
105
+ const res = await this.httpService.request(url, {
106
+ method: 'POST',
107
+ headers: { 'Content-Type': 'application/json' },
108
+ body: JSON.stringify({ username, password }),
109
+ credentials: 'include',
110
+ });
111
+
112
+ if (!res.ok) {
113
+ return fail<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
114
+ }
115
+
116
+ // TODO: Handle tokens if not using cookies
117
+
118
+ const whoAmIRes = await this.whoAmI();
119
+
120
+ if (!whoAmIRes.ok) {
121
+ return whoAmIRes;
122
+ }
123
+
124
+ return ok<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>({
125
+ result: whoAmIRes.result.user,
126
+ metadata: whoAmIRes.metadata,
127
+ });
128
+ } catch (err) {
129
+ console.error(err);
130
+
131
+ return fail<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>({
132
+ error: {
133
+ code: ErrorCode.UnknownError,
134
+ message: 'Failed signing in',
135
+ metadata: {} as EmptyMetadataDto,
136
+ },
137
+ });
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Deauthenticates current user
143
+ *
144
+ * @return {Promise<void>}
145
+ * @throws {Error} Error if fetch fails
146
+ */
147
+ public async signOut(): Promise<ApiResponseDto<undefined, EmptyMetadataDto>> {
148
+ try {
149
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/signout');
150
+ const res = await this.httpService.request(url, { credentials: 'include' });
151
+
152
+ if (!res.ok) {
153
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
154
+ }
155
+
156
+ this.user = undefined;
157
+ return ok<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
158
+ } catch (err) {
159
+ console.error(err);
160
+
161
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>({
162
+ error: {
163
+ code: ErrorCode.UnknownError,
164
+ message: 'Failed signing out',
165
+ metadata: {} as EmptyMetadataDto,
166
+ },
167
+ });
168
+ }
169
+ }
170
+
171
+ /**
172
+ * If any API response returns an "Unauthenticated" response, call this method
173
+ * to update local authentication state to unauthenticated
174
+ */
175
+ public handleNoAuthApiResponse(): void {
176
+ this.user = undefined;
177
+ }
178
+
179
+ // #region Client-side authorization helpers
180
+
181
+ /**
182
+ * True if a user is currently loaded (post whoAmI/signIn)
183
+ */
184
+ public isAuthenticated(): boolean {
185
+ return !!this.user;
186
+ }
187
+ }
@@ -0,0 +1,165 @@
1
+ import { apiInitializationService, IHttpService } from '@services';
2
+ import { ApiErrorResponseDto, ApiResponseDto, ApiSuccessResponseDto, EmptyMetadataDto, ErrorCode, ReadMetadataDto, RoleDto } from '@data';
3
+ import { fail, ok } from '@utils/result';
4
+
5
+ /**
6
+ * Client for authorization management operations
7
+ *
8
+ * @export
9
+ * @class AuthorizationManagementControllerClient
10
+ */
11
+ export class AuthorizationManagementControllerClient {
12
+ /**
13
+ * Constructor
14
+ * @param baseControllerPath Base path to API controller
15
+ * @param httpService HTTP service implementation to use for requests
16
+ */
17
+ constructor(
18
+ protected readonly baseControllerPath: string = 'AuthorizationManagement',
19
+ httpService?: IHttpService,
20
+ ) {
21
+ this._httpService = httpService;
22
+ }
23
+
24
+ // #region HTTP service
25
+ private readonly _httpService?: IHttpService = undefined;
26
+
27
+ /**
28
+ * Gets globally selected HTTP service
29
+ */
30
+ protected get httpService(): IHttpService {
31
+ return this._httpService || apiInitializationService._getHttpService();
32
+ }
33
+
34
+ // #endregion
35
+
36
+ /**
37
+ * Gets all roles in the system
38
+ * @param includeClaims - Whether to include claims in the response
39
+ * @param signal - Optional cancellation signal
40
+ * @returns List of all roles
41
+ */
42
+ public async getAllRoles(includeClaims: boolean, signal?: AbortSignal): Promise<ApiResponseDto<RoleDto[], ReadMetadataDto>> {
43
+ try {
44
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/GetAllRoles?includeClaims=${includeClaims}`);
45
+ const res = await this.httpService.request(url, {
46
+ credentials: 'include',
47
+ signal,
48
+ });
49
+
50
+ if (!res.ok) {
51
+ return fail<ApiSuccessResponseDto<RoleDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
52
+ }
53
+
54
+ return ok<ApiSuccessResponseDto<RoleDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
55
+ } catch (err) {
56
+ console.error(err);
57
+
58
+ return fail<ApiSuccessResponseDto<RoleDto[], ReadMetadataDto>, ApiErrorResponseDto>({
59
+ error: {
60
+ code: ErrorCode.UnknownError,
61
+ message: 'Unknown error fetching all roles',
62
+ metadata: {} as EmptyMetadataDto,
63
+ },
64
+ });
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Gets a role with its claims
70
+ * @param roleName - The name of the role
71
+ * @param signal
72
+ * @returns The role with its claims
73
+ */
74
+ public async getRoleWithClaims(roleName: string, signal?: AbortSignal): Promise<ApiResponseDto<RoleDto, ReadMetadataDto>> {
75
+ try {
76
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/GetRoleWithClaims/${encodeURIComponent(roleName)}`);
77
+ const res = await this.httpService.request(url, {
78
+ credentials: 'include',
79
+ signal,
80
+ });
81
+
82
+ if (!res.ok) {
83
+ return fail<ApiSuccessResponseDto<RoleDto, ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
84
+ }
85
+
86
+ return ok<ApiSuccessResponseDto<RoleDto, ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
87
+ } catch (err) {
88
+ console.error(err);
89
+
90
+ return fail<ApiSuccessResponseDto<RoleDto, ReadMetadataDto>, ApiErrorResponseDto>({
91
+ error: {
92
+ code: ErrorCode.UnknownError,
93
+ message: 'Unknown error fetching role with claims',
94
+ metadata: {} as EmptyMetadataDto,
95
+ },
96
+ });
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Creates or updates a role
102
+ * @param roleDto - The role to create or update
103
+ * @returns The created or updated role
104
+ */
105
+ public async upsertRole(roleDto: RoleDto): Promise<ApiResponseDto<RoleDto, EmptyMetadataDto>> {
106
+ try {
107
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/UpsertRole`);
108
+ const res = await this.httpService.request(url, {
109
+ method: 'PUT',
110
+ headers: {
111
+ 'Content-Type': 'application/json',
112
+ },
113
+ body: JSON.stringify(roleDto),
114
+ credentials: 'include',
115
+ });
116
+
117
+ if (!res.ok) {
118
+ return fail<ApiSuccessResponseDto<RoleDto, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
119
+ }
120
+
121
+ return ok<ApiSuccessResponseDto<RoleDto, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
122
+ } catch (err) {
123
+ console.error(err);
124
+
125
+ return fail<ApiSuccessResponseDto<RoleDto, EmptyMetadataDto>, ApiErrorResponseDto>({
126
+ error: {
127
+ code: ErrorCode.UnknownError,
128
+ message: 'Unknown error upserting role',
129
+ metadata: {} as EmptyMetadataDto,
130
+ },
131
+ });
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Deletes a role
137
+ * @param roleName - The name of the role to delete
138
+ * @returns Promise that resolves when the role is deleted successfully
139
+ */
140
+ public async deleteRole(roleName: string): Promise<ApiResponseDto<undefined, EmptyMetadataDto>> {
141
+ try {
142
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/DeleteRole/${encodeURIComponent(roleName)}`);
143
+ const res = await this.httpService.request(url, {
144
+ method: 'DELETE',
145
+ credentials: 'include',
146
+ });
147
+
148
+ if (!res.ok) {
149
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
150
+ }
151
+
152
+ return ok<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(undefined);
153
+ } catch (err) {
154
+ console.error(err);
155
+
156
+ return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>({
157
+ error: {
158
+ code: ErrorCode.UnknownError,
159
+ message: `Unknown error while deleting the role ${roleName}`,
160
+ metadata: {} as EmptyMetadataDto,
161
+ },
162
+ });
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,2 @@
1
+ export * from './AuthorizationManagementControllerClient';
2
+ export * from './AuthService';
@@ -0,0 +1 @@
1
+ export * from './client';
@@ -0,0 +1,2 @@
1
+ export * from './api';
2
+ export * from './auth';
@@ -0,0 +1,47 @@
1
+ import { IPolicy, PolicyBase } from '@data';
2
+
3
+ /**
4
+ * Checks if a policy is valid for the given parameters.
5
+ *
6
+ * @param policy Policy to check, either an instance or a class.
7
+ * @param params Parameters to pass to the policy check function.
8
+ * @returns A promise that resolves if the policy is valid, rejects otherwise.
9
+ */
10
+ export async function check<TParams extends unknown[]>(policy: IPolicy<TParams> | (new () => IPolicy<TParams>), ...params: TParams): Promise<boolean> {
11
+ // If passed an instance of a policy
12
+ if (policy instanceof PolicyBase) {
13
+ return (policy as IPolicy<TParams>).check(...params);
14
+ }
15
+ // If passed a policy class
16
+ else {
17
+ return new (policy as new () => IPolicy<TParams>)().check(...params);
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Composes multiple policies into a single policy.
23
+ *
24
+ * @param composition Composition method, either 'AND' or 'OR'.
25
+ * @param policies Policies to compose.
26
+ * @returns A new policy that represents the composition of the policies.
27
+ */
28
+ export function compose<TParams extends unknown[]>(composition: 'AND' | 'OR', ...policies: IPolicy<TParams>[]): IPolicy<TParams> {
29
+ return {
30
+ check: async (...params: TParams): Promise<boolean> => {
31
+ // Check all policies
32
+ if (composition === 'AND') {
33
+ const results = await Promise.allSettled(policies.map(policy => policy.check(...params)));
34
+ return results.every(result => result);
35
+ }
36
+ // Check any policies, exit as soon as any are true
37
+ else if (composition === 'OR') {
38
+ const results = await Promise.allSettled(policies.map(policy => policy.check(...params)));
39
+ return results.some(result => result);
40
+ }
41
+ // Invalid composition
42
+ else {
43
+ throw new Error('Invalid composition');
44
+ }
45
+ },
46
+ };
47
+ }