@intellegens/cornerstone-client 0.0.0-experimental-upgrade-20260302-1

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 (251) hide show
  1. package/README.md +256 -0
  2. package/demo/index.ts +29 -0
  3. package/demo/public_html/favicon.ico +0 -0
  4. package/demo/public_html/index.html +106 -0
  5. package/demo/public_html/websettings.json +3 -0
  6. package/dist/adapters/CollectionViewAdapter/index.d.ts +198 -0
  7. package/dist/adapters/CollectionViewAdapter/index.integration.test.d.ts +1 -0
  8. package/dist/adapters/CollectionViewAdapter/index.integration.test.js +163 -0
  9. package/dist/adapters/CollectionViewAdapter/index.js +381 -0
  10. package/dist/adapters/SearchAdapter/index.d.ts +55 -0
  11. package/dist/adapters/SearchAdapter/index.js +233 -0
  12. package/dist/adapters/index.d.ts +2 -0
  13. package/dist/adapters/index.js +2 -0
  14. package/dist/data/api/dto/PropertyPathDto.d.ts +4 -0
  15. package/dist/data/api/dto/PropertyPathDto.js +1 -0
  16. package/dist/data/api/dto/ReadOptionsDto.d.ts +8 -0
  17. package/dist/data/api/dto/ReadOptionsDto.js +1 -0
  18. package/dist/data/api/dto/ReadResultDto.d.ts +12 -0
  19. package/dist/data/api/dto/ReadResultDto.js +1 -0
  20. package/dist/data/api/dto/ReadResultMetadataDto.d.ts +8 -0
  21. package/dist/data/api/dto/ReadResultMetadataDto.js +1 -0
  22. package/dist/data/api/dto/crud/CrudMetadataDto.d.ts +4 -0
  23. package/dist/data/api/dto/crud/CrudMetadataDto.js +1 -0
  24. package/dist/data/api/dto/crud/index.d.ts +1 -0
  25. package/dist/data/api/dto/crud/index.js +1 -0
  26. package/dist/data/api/dto/index.d.ts +4 -0
  27. package/dist/data/api/dto/index.js +4 -0
  28. package/dist/data/api/dto/read/ReadMetadataDto.d.ts +8 -0
  29. package/dist/data/api/dto/read/ReadMetadataDto.js +1 -0
  30. package/dist/data/api/dto/read/ReadSelectedDefinitionDto.d.ts +18 -0
  31. package/dist/data/api/dto/read/ReadSelectedDefinitionDto.js +1 -0
  32. package/dist/data/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.d.ts +22 -0
  33. package/dist/data/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.js +1 -0
  34. package/dist/data/api/dto/read/ReadSelectedNestedCriteriaDto.d.ts +18 -0
  35. package/dist/data/api/dto/read/ReadSelectedNestedCriteriaDto.js +1 -0
  36. package/dist/data/api/dto/read/ReadSelectedOrderingDefinitionDto.d.ts +7 -0
  37. package/dist/data/api/dto/read/ReadSelectedOrderingDefinitionDto.js +1 -0
  38. package/dist/data/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.d.ts +14 -0
  39. package/dist/data/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.js +1 -0
  40. package/dist/data/api/dto/read/ReadSelectedPaginationDefinitionDto.d.ts +13 -0
  41. package/dist/data/api/dto/read/ReadSelectedPaginationDefinitionDto.js +1 -0
  42. package/dist/data/api/dto/read/ReadSelectedSearchDefinitionBuilder.d.ts +167 -0
  43. package/dist/data/api/dto/read/ReadSelectedSearchDefinitionBuilder.js +267 -0
  44. package/dist/data/api/dto/read/ReadSelectedSearchDefinitionDto.d.ts +33 -0
  45. package/dist/data/api/dto/read/ReadSelectedSearchDefinitionDto.js +1 -0
  46. package/dist/data/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.d.ts +114 -0
  47. package/dist/data/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.js +1 -0
  48. package/dist/data/api/dto/read/index.d.ts +10 -0
  49. package/dist/data/api/dto/read/index.js +10 -0
  50. package/dist/data/api/dto/response/ApiErrorDto.d.ts +17 -0
  51. package/dist/data/api/dto/response/ApiErrorDto.js +1 -0
  52. package/dist/data/api/dto/response/ApiErrorResponseDto.d.ts +11 -0
  53. package/dist/data/api/dto/response/ApiErrorResponseDto.js +1 -0
  54. package/dist/data/api/dto/response/ApiResponseDto.d.ts +3 -0
  55. package/dist/data/api/dto/response/ApiResponseDto.js +1 -0
  56. package/dist/data/api/dto/response/ApiSuccessResponseDto.d.ts +13 -0
  57. package/dist/data/api/dto/response/ApiSuccessResponseDto.js +1 -0
  58. package/dist/data/api/dto/response/EmptyMetadataDto.d.ts +4 -0
  59. package/dist/data/api/dto/response/EmptyMetadataDto.js +1 -0
  60. package/dist/data/api/dto/response/MetadataDto.d.ts +25 -0
  61. package/dist/data/api/dto/response/MetadataDto.js +1 -0
  62. package/dist/data/api/dto/response/index.d.ts +5 -0
  63. package/dist/data/api/dto/response/index.js +5 -0
  64. package/dist/data/api/enum/index.d.ts +2 -0
  65. package/dist/data/api/enum/index.js +2 -0
  66. package/dist/data/api/enum/read/ReadSelectedCollectionOperator.d.ts +16 -0
  67. package/dist/data/api/enum/read/ReadSelectedCollectionOperator.js +17 -0
  68. package/dist/data/api/enum/read/ReadSelectedComparisonOperator.d.ts +69 -0
  69. package/dist/data/api/enum/read/ReadSelectedComparisonOperator.js +76 -0
  70. package/dist/data/api/enum/read/ReadSelectedLogicalOperator.d.ts +15 -0
  71. package/dist/data/api/enum/read/ReadSelectedLogicalOperator.js +16 -0
  72. package/dist/data/api/enum/read/ReadSelectedOrderingDirection.d.ts +13 -0
  73. package/dist/data/api/enum/read/ReadSelectedOrderingDirection.js +14 -0
  74. package/dist/data/api/enum/read/ReadSelectedPropertyType.d.ts +66 -0
  75. package/dist/data/api/enum/read/ReadSelectedPropertyType.js +75 -0
  76. package/dist/data/api/enum/read/index.d.ts +5 -0
  77. package/dist/data/api/enum/read/index.js +5 -0
  78. package/dist/data/api/enum/response/ApiErrorCodes.d.ts +7 -0
  79. package/dist/data/api/enum/response/ApiErrorCodes.js +8 -0
  80. package/dist/data/api/enum/response/ErrorCode.d.ts +13 -0
  81. package/dist/data/api/enum/response/ErrorCode.js +14 -0
  82. package/dist/data/api/enum/response/index.d.ts +1 -0
  83. package/dist/data/api/enum/response/index.js +1 -0
  84. package/dist/data/api/index.d.ts +3 -0
  85. package/dist/data/api/index.js +3 -0
  86. package/dist/data/api/interface/ICommonIdentifiable.d.ts +7 -0
  87. package/dist/data/api/interface/ICommonIdentifiable.js +1 -0
  88. package/dist/data/api/interface/IConcurrencySafe.d.ts +9 -0
  89. package/dist/data/api/interface/IConcurrencySafe.js +2 -0
  90. package/dist/data/api/interface/IIdentifiable.d.ts +11 -0
  91. package/dist/data/api/interface/IIdentifiable.js +1 -0
  92. package/dist/data/api/interface/IIdentifiableSecondary.d.ts +9 -0
  93. package/dist/data/api/interface/IIdentifiableSecondary.js +1 -0
  94. package/dist/data/api/interface/index.d.ts +3 -0
  95. package/dist/data/api/interface/index.js +3 -0
  96. package/dist/data/auth/dto/ClaimDto.d.ts +4 -0
  97. package/dist/data/auth/dto/ClaimDto.js +1 -0
  98. package/dist/data/auth/dto/RegisterRequestDto.d.ts +4 -0
  99. package/dist/data/auth/dto/RegisterRequestDto.js +1 -0
  100. package/dist/data/auth/dto/RoleDto.d.ts +5 -0
  101. package/dist/data/auth/dto/RoleDto.js +1 -0
  102. package/dist/data/auth/dto/SignInRequestDto.d.ts +4 -0
  103. package/dist/data/auth/dto/SignInRequestDto.js +1 -0
  104. package/dist/data/auth/dto/TokensDto.d.ts +4 -0
  105. package/dist/data/auth/dto/TokensDto.js +1 -0
  106. package/dist/data/auth/dto/UserDto.d.ts +17 -0
  107. package/dist/data/auth/dto/UserDto.js +1 -0
  108. package/dist/data/auth/dto/UserInfoDto.d.ts +14 -0
  109. package/dist/data/auth/dto/UserInfoDto.js +1 -0
  110. package/dist/data/auth/dto/index.d.ts +5 -0
  111. package/dist/data/auth/dto/index.js +5 -0
  112. package/dist/data/auth/index.d.ts +2 -0
  113. package/dist/data/auth/index.js +2 -0
  114. package/dist/data/auth/policy.d.ts +52 -0
  115. package/dist/data/auth/policy.js +44 -0
  116. package/dist/data/index.d.ts +2 -0
  117. package/dist/data/index.js +2 -0
  118. package/dist/index.d.ts +4 -0
  119. package/dist/index.js +4 -0
  120. package/dist/services/api/ApiCrudControllerClient/index.d.ts +41 -0
  121. package/dist/services/api/ApiCrudControllerClient/index.integration.test.d.ts +1 -0
  122. package/dist/services/api/ApiCrudControllerClient/index.integration.test.js +34 -0
  123. package/dist/services/api/ApiCrudControllerClient/index.js +116 -0
  124. package/dist/services/api/ApiInitializationService/index.d.ts +106 -0
  125. package/dist/services/api/ApiInitializationService/index.js +208 -0
  126. package/dist/services/api/ApiReadControllerClient/index.d.ts +40 -0
  127. package/dist/services/api/ApiReadControllerClient/index.integration.test.d.ts +1 -0
  128. package/dist/services/api/ApiReadControllerClient/index.integration.test.js +59 -0
  129. package/dist/services/api/ApiReadControllerClient/index.js +111 -0
  130. package/dist/services/api/HttpService/FetchHttpService.d.ts +7 -0
  131. package/dist/services/api/HttpService/FetchHttpService.integration.test.d.ts +1 -0
  132. package/dist/services/api/HttpService/FetchHttpService.integration.test.js +52 -0
  133. package/dist/services/api/HttpService/FetchHttpService.js +29 -0
  134. package/dist/services/api/HttpService/HttpRequestConfig.d.ts +10 -0
  135. package/dist/services/api/HttpService/HttpRequestConfig.js +1 -0
  136. package/dist/services/api/HttpService/HttpResponse.d.ts +11 -0
  137. package/dist/services/api/HttpService/HttpResponse.js +3 -0
  138. package/dist/services/api/HttpService/IHttpService.d.ts +13 -0
  139. package/dist/services/api/HttpService/IHttpService.js +3 -0
  140. package/dist/services/api/HttpService/index.d.ts +9 -0
  141. package/dist/services/api/HttpService/index.js +10 -0
  142. package/dist/services/api/UserManagementControllerClient/index.d.ts +41 -0
  143. package/dist/services/api/UserManagementControllerClient/index.integration.test.d.ts +1 -0
  144. package/dist/services/api/UserManagementControllerClient/index.integration.test.js +60 -0
  145. package/dist/services/api/UserManagementControllerClient/index.js +117 -0
  146. package/dist/services/api/index.d.ts +5 -0
  147. package/dist/services/api/index.js +5 -0
  148. package/dist/services/auth/client/AuthService/index.d.ts +75 -0
  149. package/dist/services/auth/client/AuthService/index.js +200 -0
  150. package/dist/services/auth/client/AuthorizationManagementControllerClient/index.d.ts +48 -0
  151. package/dist/services/auth/client/AuthorizationManagementControllerClient/index.integration.test.d.ts +1 -0
  152. package/dist/services/auth/client/AuthorizationManagementControllerClient/index.integration.test.js +89 -0
  153. package/dist/services/auth/client/AuthorizationManagementControllerClient/index.js +148 -0
  154. package/dist/services/auth/client/index.d.ts +2 -0
  155. package/dist/services/auth/client/index.js +2 -0
  156. package/dist/services/auth/index.d.ts +1 -0
  157. package/dist/services/auth/index.js +1 -0
  158. package/dist/services/index.d.ts +2 -0
  159. package/dist/services/index.js +2 -0
  160. package/dist/utils/authorization/index.d.ts +17 -0
  161. package/dist/utils/authorization/index.js +45 -0
  162. package/dist/utils/index.d.ts +2 -0
  163. package/dist/utils/index.js +2 -0
  164. package/dist/utils/result/index.d.ts +21 -0
  165. package/dist/utils/result/index.js +16 -0
  166. package/dist/utils/search/index.d.ts +34 -0
  167. package/dist/utils/search/index.js +106 -0
  168. package/package.json +45 -0
  169. package/src/adapters/CollectionViewAdapter/index.integration.test.ts +197 -0
  170. package/src/adapters/CollectionViewAdapter/index.ts +477 -0
  171. package/src/adapters/SearchAdapter/index.ts +302 -0
  172. package/src/adapters/index.ts +2 -0
  173. package/src/data/api/dto/PropertyPathDto.ts +4 -0
  174. package/src/data/api/dto/ReadOptionsDto.ts +8 -0
  175. package/src/data/api/dto/ReadResultDto.ts +13 -0
  176. package/src/data/api/dto/ReadResultMetadataDto.ts +8 -0
  177. package/src/data/api/dto/crud/CrudMetadataDto.ts +4 -0
  178. package/src/data/api/dto/crud/index.ts +1 -0
  179. package/src/data/api/dto/index.ts +4 -0
  180. package/src/data/api/dto/read/ReadMetadataDto.ts +8 -0
  181. package/src/data/api/dto/read/ReadSelectedDefinitionDto.ts +21 -0
  182. package/src/data/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.ts +25 -0
  183. package/src/data/api/dto/read/ReadSelectedNestedCriteriaDto.ts +20 -0
  184. package/src/data/api/dto/read/ReadSelectedOrderingDefinitionDto.ts +8 -0
  185. package/src/data/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.ts +16 -0
  186. package/src/data/api/dto/read/ReadSelectedPaginationDefinitionDto.ts +13 -0
  187. package/src/data/api/dto/read/ReadSelectedSearchDefinitionBuilder.ts +348 -0
  188. package/src/data/api/dto/read/ReadSelectedSearchDefinitionDto.ts +43 -0
  189. package/src/data/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.ts +186 -0
  190. package/src/data/api/dto/read/index.ts +10 -0
  191. package/src/data/api/dto/response/ApiErrorDto.ts +21 -0
  192. package/src/data/api/dto/response/ApiErrorResponseDto.ts +13 -0
  193. package/src/data/api/dto/response/ApiResponseDto.ts +7 -0
  194. package/src/data/api/dto/response/ApiSuccessResponseDto.ts +13 -0
  195. package/src/data/api/dto/response/MetadataDto.ts +24 -0
  196. package/src/data/api/dto/response/index.ts +5 -0
  197. package/src/data/api/enum/index.ts +2 -0
  198. package/src/data/api/enum/read/ReadSelectedCollectionOperator.ts +17 -0
  199. package/src/data/api/enum/read/ReadSelectedComparisonOperator.ts +96 -0
  200. package/src/data/api/enum/read/ReadSelectedLogicalOperator.ts +16 -0
  201. package/src/data/api/enum/read/ReadSelectedOrderingDirection.ts +13 -0
  202. package/src/data/api/enum/read/ReadSelectedPropertyType.ts +96 -0
  203. package/src/data/api/enum/read/index.ts +5 -0
  204. package/src/data/api/enum/response/ErrorCode.ts +13 -0
  205. package/src/data/api/enum/response/index.ts +1 -0
  206. package/src/data/api/index.ts +3 -0
  207. package/src/data/api/interface/ICommonIdentifiable.ts +9 -0
  208. package/src/data/api/interface/IConcurrencySafe.ts +9 -0
  209. package/src/data/api/interface/IIdentifiable.ts +12 -0
  210. package/src/data/api/interface/IIdentifiableSecondary.ts +9 -0
  211. package/src/data/api/interface/index.ts +3 -0
  212. package/src/data/auth/dto/ClaimDto.ts +4 -0
  213. package/src/data/auth/dto/RegisterRequestDto.ts +4 -0
  214. package/src/data/auth/dto/RoleDto.ts +6 -0
  215. package/src/data/auth/dto/SignInRequestDto.ts +4 -0
  216. package/src/data/auth/dto/TokensDto.ts +4 -0
  217. package/src/data/auth/dto/UserDto.ts +18 -0
  218. package/src/data/auth/dto/UserInfoDto.ts +15 -0
  219. package/src/data/auth/dto/index.ts +5 -0
  220. package/src/data/auth/index.ts +2 -0
  221. package/src/data/auth/policy.ts +63 -0
  222. package/src/data/index.ts +2 -0
  223. package/src/index.ts +4 -0
  224. package/src/services/api/ApiCrudControllerClient/index.integration.test.ts +46 -0
  225. package/src/services/api/ApiCrudControllerClient/index.ts +135 -0
  226. package/src/services/api/ApiInitializationService/index.ts +254 -0
  227. package/src/services/api/ApiReadControllerClient/index.integration.test.ts +71 -0
  228. package/src/services/api/ApiReadControllerClient/index.ts +137 -0
  229. package/src/services/api/HttpService/FetchHttpService.integration.test.ts +65 -0
  230. package/src/services/api/HttpService/FetchHttpService.ts +34 -0
  231. package/src/services/api/HttpService/HttpRequestConfig.ts +10 -0
  232. package/src/services/api/HttpService/HttpResponse.ts +14 -0
  233. package/src/services/api/HttpService/IHttpService.ts +17 -0
  234. package/src/services/api/HttpService/README.md +106 -0
  235. package/src/services/api/HttpService/index.ts +12 -0
  236. package/src/services/api/UserManagementControllerClient/index.integration.test.ts +69 -0
  237. package/src/services/api/UserManagementControllerClient/index.ts +134 -0
  238. package/src/services/api/index.ts +5 -0
  239. package/src/services/auth/client/AuthService/index.ts +233 -0
  240. package/src/services/auth/client/AuthorizationManagementControllerClient/index.integration.test.ts +110 -0
  241. package/src/services/auth/client/AuthorizationManagementControllerClient/index.ts +165 -0
  242. package/src/services/auth/client/index.ts +2 -0
  243. package/src/services/auth/index.ts +1 -0
  244. package/src/services/index.ts +2 -0
  245. package/src/utils/authorization/index.ts +47 -0
  246. package/src/utils/index.ts +2 -0
  247. package/src/utils/result/index.ts +25 -0
  248. package/src/utils/search/index.ts +150 -0
  249. package/tsconfig.json +19 -0
  250. package/vitest-setup.ts +43 -0
  251. package/vitest.config.ts +59 -0
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './services';
2
+ export * from './data';
3
+ export * from './adapters';
4
+ export * from './utils';
@@ -0,0 +1,41 @@
1
+ import { ApiResponseDto, EmptyMetadataDto } from '../../../data/api/dto';
2
+ import { IIdentifiable } from '../../../data/api/interface';
3
+ import { IHttpService } from '../HttpService';
4
+ import { ApiReadControllerClient } from '../ApiReadControllerClient';
5
+ /**
6
+ * Generic API client for consuming any Cornerstone CrudController
7
+ *
8
+ * @export
9
+ * @class ApiCrudControllerClient
10
+ * @template TKey - Type of the entity key (e.g., number, string, GUID, etc.)
11
+ * @template TDto - Data Transfer Object representing the entity
12
+ */
13
+ export declare class ApiCrudControllerClient<TKey, TResultDto extends IIdentifiable<TKey>, TSingleResultDto extends IIdentifiable<TKey>, TInsertRequestDto, TUpdateRequestDto> extends ApiReadControllerClient<TKey, TResultDto, TSingleResultDto> {
14
+ /**
15
+ * Constructor
16
+ * @param baseControllerPath Base path to API controller
17
+ * @param httpService HTTP service implementation to use for requests
18
+ */
19
+ constructor(baseControllerPath: string, httpService?: IHttpService);
20
+ /**
21
+ * Creates a new entity.
22
+ * @param dto - Insert request DTO
23
+ * @param {AbortSignal} [signal] - Optional cancellation signal
24
+ * @returns The created entity DTO
25
+ */
26
+ create(dto: TInsertRequestDto, signal?: AbortSignal): Promise<ApiResponseDto<TSingleResultDto, EmptyMetadataDto>>;
27
+ /**
28
+ * Updates an existing entity.
29
+ * @param id - The ID of the entity to update
30
+ * @param dto - Update request DTO
31
+ * @param {AbortSignal} [signal] - Optional cancellation signal
32
+ * @returns The updated entity DTO
33
+ */
34
+ update(id: TKey, dto: TUpdateRequestDto, signal?: AbortSignal): Promise<ApiResponseDto<TSingleResultDto, EmptyMetadataDto>>;
35
+ /**
36
+ * Deletes an entity by ID.
37
+ * @param id - The ID of the entity to delete
38
+ * @param {AbortSignal} [signal] - Optional cancellation signal
39
+ */
40
+ delete(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<undefined, EmptyMetadataDto>>;
41
+ }
@@ -0,0 +1,34 @@
1
+ import { beforeEach, describe, expect, it } from 'vitest';
2
+ import { ApiCrudControllerClient } from '.';
3
+ import { FetchHttpService } from '../HttpService';
4
+ describe('ApiCrudControllerClient', () => {
5
+ let client;
6
+ let fetchService;
7
+ const testId = 100;
8
+ beforeEach(() => {
9
+ fetchService = new FetchHttpService();
10
+ client = new ApiCrudControllerClient('/VehiclesSlim', fetchService);
11
+ });
12
+ it('should use injected HTTP service for create', async () => {
13
+ const newVehicle = { id: testId, brand: 'New Brand', model: 'New Model' };
14
+ const result = (await client.create(newVehicle));
15
+ expect(result.ok).toBe(true);
16
+ expect(result.result).toBeDefined();
17
+ expect(result.result.id).toBe(newVehicle.id);
18
+ expect(result.result.brand).toBe(newVehicle.brand);
19
+ expect(result.result.model).toBe(newVehicle.model);
20
+ });
21
+ it('should use injected HTTP service for update', async () => {
22
+ const updateVehicle = { id: testId, brand: 'Updated Brand', model: 'Updated Model' };
23
+ const result = (await client.update(testId, updateVehicle));
24
+ expect(result.ok).toBe(true);
25
+ expect(result.result).toBeDefined();
26
+ expect(result.result.id).toBe(updateVehicle.id);
27
+ expect(result.result.brand).toBe(updateVehicle.brand);
28
+ expect(result.result.model).toBe(updateVehicle.model);
29
+ });
30
+ it('should use injected HTTP service for delete', async () => {
31
+ const result = await client.delete(testId);
32
+ expect(result.ok).toBe(true);
33
+ });
34
+ });
@@ -0,0 +1,116 @@
1
+ import { apiInitializationService } from '../ApiInitializationService';
2
+ import { ApiReadControllerClient } from '../ApiReadControllerClient';
3
+ import { ErrorCode } from '../../../data';
4
+ import { fail, ok } from '../../../utils/result';
5
+ /**
6
+ * Generic API client for consuming any Cornerstone CrudController
7
+ *
8
+ * @export
9
+ * @class ApiCrudControllerClient
10
+ * @template TKey - Type of the entity key (e.g., number, string, GUID, etc.)
11
+ * @template TDto - Data Transfer Object representing the entity
12
+ */
13
+ export class ApiCrudControllerClient extends ApiReadControllerClient {
14
+ /**
15
+ * Constructor
16
+ * @param baseControllerPath Base path to API controller
17
+ * @param httpService HTTP service implementation to use for requests
18
+ */
19
+ constructor(baseControllerPath, httpService) {
20
+ super(baseControllerPath, httpService);
21
+ }
22
+ /**
23
+ * Creates a new entity.
24
+ * @param dto - Insert request DTO
25
+ * @param {AbortSignal} [signal] - Optional cancellation signal
26
+ * @returns The created entity DTO
27
+ */
28
+ async create(dto, signal) {
29
+ try {
30
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/Create`);
31
+ const res = await this.httpService.request(url, {
32
+ method: 'POST',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify(dto),
35
+ credentials: 'include',
36
+ signal,
37
+ });
38
+ if (!res.ok) {
39
+ return fail(await res.json());
40
+ }
41
+ return ok(await res.json());
42
+ }
43
+ catch (err) {
44
+ console.error(err);
45
+ return fail({
46
+ error: {
47
+ code: ErrorCode.UnknownError,
48
+ message: 'Unknown error occurred while creating the record.',
49
+ metadata: {},
50
+ },
51
+ });
52
+ }
53
+ }
54
+ /**
55
+ * Updates an existing entity.
56
+ * @param id - The ID of the entity to update
57
+ * @param dto - Update request DTO
58
+ * @param {AbortSignal} [signal] - Optional cancellation signal
59
+ * @returns The updated entity DTO
60
+ */
61
+ async update(id, dto, signal) {
62
+ try {
63
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/Update?id=${encodeURIComponent(String(id))}`);
64
+ const res = await this.httpService.request(url, {
65
+ method: 'PUT',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ body: JSON.stringify(dto),
68
+ credentials: 'include',
69
+ signal,
70
+ });
71
+ if (!res.ok) {
72
+ return fail(await res.json());
73
+ }
74
+ return ok(await res.json());
75
+ }
76
+ catch (err) {
77
+ console.error(err);
78
+ return fail({
79
+ error: {
80
+ code: ErrorCode.UnknownError,
81
+ message: `Unknown error occurred while updating the record with id ${id}`,
82
+ metadata: {},
83
+ },
84
+ });
85
+ }
86
+ }
87
+ /**
88
+ * Deletes an entity by ID.
89
+ * @param id - The ID of the entity to delete
90
+ * @param {AbortSignal} [signal] - Optional cancellation signal
91
+ */
92
+ async delete(id, signal) {
93
+ try {
94
+ const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/Delete?id=${encodeURIComponent(String(id))}`);
95
+ const res = await this.httpService.request(url, {
96
+ method: 'DELETE',
97
+ credentials: 'include',
98
+ signal,
99
+ });
100
+ if (!res.ok) {
101
+ return fail(await res.json());
102
+ }
103
+ return ok(await res.json());
104
+ }
105
+ catch (err) {
106
+ console.error(err);
107
+ return fail({
108
+ error: {
109
+ code: ErrorCode.UnknownError,
110
+ message: `Unknown error occurred while deleting the record with id ${id}`,
111
+ metadata: {},
112
+ },
113
+ });
114
+ }
115
+ }
116
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Generic shared settings interface - can represent any user-configured settings structure
3
+ * The actual properties depend on what users configure in their appsettings.json or environment variables
4
+ */
5
+ type ISharedSettings = {
6
+ [key: string]: unknown;
7
+ };
8
+ import { IHttpService } from '../HttpService';
9
+ /**
10
+ * Central API configuration service, fetches and exposes Cornerstone API configuration
11
+ *
12
+ * @export
13
+ * @class ApiInitializationService
14
+ */
15
+ export declare class ApiInitializationService {
16
+ /**
17
+ * If API base URL detection was completed
18
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
19
+ */
20
+ _apiBaseUrlDetected: boolean;
21
+ /**
22
+ * If API base URL detection was completed, this property will hold the method by which detection was performed
23
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
24
+ */
25
+ _apiBaseUrlDetectionMethod: string | undefined;
26
+ /**
27
+ * If API base URL detection was completed, this property will hold the detected API base URL
28
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
29
+ */
30
+ _apiBaseUrl: string | undefined;
31
+ /**
32
+ * If API base URL detection has failed, this property will hold the error with which it has failed
33
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
34
+ */
35
+ _apiBaseError: Error | undefined;
36
+ appConfig?: ISharedSettings | undefined;
37
+ private _httpService;
38
+ private _apiBaseUrlPromise;
39
+ /**
40
+ * Initializes the API configuration
41
+ *
42
+ * This method calls all methods that need to be called during the API configuration phase:
43
+ * - Starts detection of API base URL.
44
+ * - Fetches shared settings from the server.
45
+ *
46
+ * @async
47
+ * @param httpService - HTTP service implementation to use for requests
48
+ * @param {AbortSignal} [signal] - Optional cancellation signal
49
+ * @return {Promise<void>} Resolves when initialization is complete.
50
+ */
51
+ initialize({ httpService, signal, }?: {
52
+ httpService?: IHttpService;
53
+ signal?: AbortSignal;
54
+ }): Promise<void>;
55
+ /**
56
+ * Gets configured HTTP service
57
+ * @returns
58
+ */
59
+ _getHttpService(): IHttpService;
60
+ /**
61
+ * Tries detecting API base URL by multiple methods
62
+ *
63
+ * - Checks the response headers of the current URL for the `CORNERSTONE-API-BASEURL` header.
64
+ * - Attempts to load the `websettings.json` file and looks for an `api` field.
65
+ * - Defaults to `undefined`.
66
+ *
67
+ * IMPORTANT: This method is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
68
+ *
69
+ * @async
70
+ * @param {AbortSignal} [signal] - Optional cancellation signal
71
+ * @return {Promise<string | undefined>} Returns detected API base URL
72
+ * @throws {Error} Throws error if either of the detection methods fails
73
+ */
74
+ _getApiBaseUrl(signal?: AbortSignal): Promise<string | undefined>;
75
+ /**
76
+ * Composes a full API URL for a provided endpoint path.
77
+ *
78
+ * @async
79
+ * @param relativeEndpointPathSections Relative endpoint path sections
80
+ * @return {Promise<string | undefined>} Returns the API endpoint's URL
81
+ * @throws {Error} Throws error if API base URL detection fails
82
+ */
83
+ getApiUrl(...relativeEndpointPathSections: string[]): Promise<string>;
84
+ /**
85
+ * Removes starting '/' character
86
+ * @param str String to remove the starting '/' character from
87
+ * @returns String with starting '/' character removed
88
+ */
89
+ private removeStartsWithSlashChar;
90
+ /**
91
+ * Removes ending '/' character
92
+ * @param str String to remove the ending '/' character from
93
+ * @returns String with ending '/' character removed
94
+ */
95
+ private removeEndsWithSlashChar;
96
+ /**
97
+ * Fetches initialization info (shared settings) from the server
98
+ * @returns Promise that resolves to shared settings or undefined if the request fails
99
+ */
100
+ private _getAppConfig;
101
+ }
102
+ /**
103
+ * Singleton instance of ApiInitializationService
104
+ */
105
+ export declare const apiInitializationService: ApiInitializationService;
106
+ export {};
@@ -0,0 +1,208 @@
1
+ // websettings.json configuration file contents type
2
+ import { fail, ok } from '../../../utils';
3
+ import { defaultHttpService } from '../HttpService';
4
+ /**
5
+ * Central API configuration service, fetches and exposes Cornerstone API configuration
6
+ *
7
+ * @export
8
+ * @class ApiInitializationService
9
+ */
10
+ export class ApiInitializationService {
11
+ /**
12
+ * If API base URL detection was completed
13
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
14
+ */
15
+ _apiBaseUrlDetected = false;
16
+ // #region HTTP service
17
+ /**
18
+ * If API base URL detection was completed, this property will hold the method by which detection was performed
19
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
20
+ */
21
+ _apiBaseUrlDetectionMethod = undefined;
22
+ /**
23
+ * If API base URL detection was completed, this property will hold the detected API base URL
24
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
25
+ */
26
+ _apiBaseUrl = undefined;
27
+ // #endregion
28
+ // #region API Base URL detection
29
+ /**
30
+ * If API base URL detection has failed, this property will hold the error with which it has failed
31
+ * IMPORTANT: This property is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
32
+ */
33
+ _apiBaseError = undefined;
34
+ // #region config App
35
+ appConfig;
36
+ _httpService = defaultHttpService;
37
+ _apiBaseUrlPromise = undefined;
38
+ /**
39
+ * Initializes the API configuration
40
+ *
41
+ * This method calls all methods that need to be called during the API configuration phase:
42
+ * - Starts detection of API base URL.
43
+ * - Fetches shared settings from the server.
44
+ *
45
+ * @async
46
+ * @param httpService - HTTP service implementation to use for requests
47
+ * @param {AbortSignal} [signal] - Optional cancellation signal
48
+ * @return {Promise<void>} Resolves when initialization is complete.
49
+ */
50
+ async initialize({ httpService, signal, } = {}) {
51
+ // Store configuration
52
+ if (httpService !== undefined)
53
+ this._httpService = httpService;
54
+ // (Pre)detect API base URL
55
+ await this._getApiBaseUrl(signal);
56
+ // Initialize app config
57
+ await this._getAppConfig();
58
+ }
59
+ /**
60
+ * Gets configured HTTP service
61
+ * @returns
62
+ */
63
+ _getHttpService() {
64
+ return this._httpService;
65
+ }
66
+ /**
67
+ * Tries detecting API base URL by multiple methods
68
+ *
69
+ * - Checks the response headers of the current URL for the `CORNERSTONE-API-BASEURL` header.
70
+ * - Attempts to load the `websettings.json` file and looks for an `api` field.
71
+ * - Defaults to `undefined`.
72
+ *
73
+ * IMPORTANT: This method is not meant to be used in normal cases - when ever possible use the .getApiUrl(relativeEndpointPath: string) method instead.
74
+ *
75
+ * @async
76
+ * @param {AbortSignal} [signal] - Optional cancellation signal
77
+ * @return {Promise<string | undefined>} Returns detected API base URL
78
+ * @throws {Error} Throws error if either of the detection methods fails
79
+ */
80
+ async _getApiBaseUrl(signal) {
81
+ // Check if API already detected; don't reattempt detection
82
+ if (this._apiBaseUrlDetected)
83
+ return this._apiBaseUrl;
84
+ // Check if detection already in progress; don't allow multiple detections in parallel
85
+ if (this._apiBaseUrlPromise)
86
+ return this._apiBaseUrlPromise;
87
+ // Detect API base URL
88
+ return (this._apiBaseUrlPromise = new Promise((resolve, reject) => (async () => {
89
+ // Reset
90
+ this._apiBaseUrlDetected = false;
91
+ this._apiBaseUrlDetectionMethod = undefined;
92
+ this._apiBaseUrl = undefined;
93
+ this._apiBaseError = undefined;
94
+ // Check CORNERSTONE-API-BASEURL header for API base URL
95
+ try {
96
+ const currentUrlResponse = await this._httpService.request(window.location.href, {
97
+ method: 'GET',
98
+ signal,
99
+ });
100
+ const apiHeader = currentUrlResponse.headers['CORNERSTONE-API-BASEURL'] || currentUrlResponse.headers['cornerstone-api-baseurl'] || null;
101
+ if (apiHeader) {
102
+ this._apiBaseUrlDetected = true;
103
+ this._apiBaseUrlDetectionMethod = 'GET / Header:CORNERSTONE-API-BASEURL';
104
+ this._apiBaseUrl = apiHeader;
105
+ this._apiBaseError = undefined;
106
+ this._apiBaseUrlPromise = undefined;
107
+ return resolve(this._apiBaseUrl);
108
+ }
109
+ }
110
+ catch (err) {
111
+ this._apiBaseError = err instanceof Error ? err : new Error('Failed loading API base URL from response header!');
112
+ }
113
+ // Check ./websettings.json header for API base URL
114
+ try {
115
+ const webSettingsResponse = await this._httpService.request('./websettings.json', {
116
+ method: 'GET',
117
+ signal,
118
+ });
119
+ if (webSettingsResponse.status === 404)
120
+ return (this._apiBaseUrl = undefined);
121
+ const webSettings = await webSettingsResponse.json();
122
+ if (webSettings?.api) {
123
+ this._apiBaseUrlDetected = true;
124
+ this._apiBaseUrlDetectionMethod = 'GET websettings.json';
125
+ this._apiBaseUrl = webSettings.api;
126
+ this._apiBaseError = undefined;
127
+ this._apiBaseUrlPromise = undefined;
128
+ return resolve(this._apiBaseUrl);
129
+ }
130
+ }
131
+ catch (err) {
132
+ this._apiBaseError = err instanceof Error ? err : new Error('Failed loading API base URL from settings file!');
133
+ }
134
+ // Check if error caught during any of the detection methods
135
+ if (this._apiBaseError !== undefined) {
136
+ this._apiBaseUrlDetected = false;
137
+ this._apiBaseUrlDetectionMethod = undefined;
138
+ this._apiBaseUrl = undefined;
139
+ this._apiBaseUrlPromise = undefined;
140
+ return reject(this._apiBaseError);
141
+ }
142
+ // Default to no API found
143
+ this._apiBaseUrlDetected = true;
144
+ this._apiBaseUrlDetectionMethod = undefined;
145
+ this._apiBaseUrl = undefined;
146
+ this._apiBaseError = undefined;
147
+ this._apiBaseUrlPromise = undefined;
148
+ return resolve(this._apiBaseUrl);
149
+ })()));
150
+ }
151
+ /**
152
+ * Composes a full API URL for a provided endpoint path.
153
+ *
154
+ * @async
155
+ * @param relativeEndpointPathSections Relative endpoint path sections
156
+ * @return {Promise<string | undefined>} Returns the API endpoint's URL
157
+ * @throws {Error} Throws error if API base URL detection fails
158
+ */
159
+ async getApiUrl(...relativeEndpointPathSections) {
160
+ const apiBaseUrl = await this._getApiBaseUrl();
161
+ const domain = !apiBaseUrl ? '/' : `${this.removeEndsWithSlashChar(apiBaseUrl)}/`;
162
+ const path = relativeEndpointPathSections.map(section => this.removeStartsWithSlashChar(this.removeEndsWithSlashChar(section))).join('/');
163
+ return `${domain}${path}`;
164
+ }
165
+ /**
166
+ * Removes starting '/' character
167
+ * @param str String to remove the starting '/' character from
168
+ * @returns String with starting '/' character removed
169
+ */
170
+ removeStartsWithSlashChar(str) {
171
+ return !str.startsWith('/') ? str : str.substring(1);
172
+ }
173
+ // #endregion
174
+ /**
175
+ * Removes ending '/' character
176
+ * @param str String to remove the ending '/' character from
177
+ * @returns String with ending '/' character removed
178
+ */
179
+ removeEndsWithSlashChar(str) {
180
+ return !str.endsWith('/') ? str : str.substring(0, str.length - 1);
181
+ }
182
+ /**
183
+ * Fetches initialization info (shared settings) from the server
184
+ * @returns Promise that resolves to shared settings or undefined if the request fails
185
+ */
186
+ async _getAppConfig() {
187
+ try {
188
+ const response = await fetch(`${this._apiBaseUrl}/system/init`, { credentials: 'include' });
189
+ if (!response.ok) {
190
+ throw fail(await response.json());
191
+ }
192
+ const apiResponse = ok(await response.json());
193
+ if (!apiResponse.ok) {
194
+ throw apiResponse.error;
195
+ }
196
+ // Return the settings from the nested structure
197
+ this.appConfig = apiResponse.result.appSettings;
198
+ }
199
+ catch (error) {
200
+ console.error('Failed to get app config', error);
201
+ this.appConfig = undefined;
202
+ }
203
+ }
204
+ }
205
+ /**
206
+ * Singleton instance of ApiInitializationService
207
+ */
208
+ export const apiInitializationService = new ApiInitializationService();
@@ -0,0 +1,40 @@
1
+ import { ApiResponseDto, EmptyMetadataDto, ReadMetadataDto, ReadSelectedDefinitionDto } from '../../../data/api/dto';
2
+ import { IIdentifiable } from '../../../data/api/interface';
3
+ import { IHttpService } from '../HttpService';
4
+ /**
5
+ * Base client for read-only API controllers
6
+ */
7
+ export declare class ApiReadControllerClient<TKey, TResultDto extends IIdentifiable<TKey>, TSingleResultDto extends IIdentifiable<TKey>> {
8
+ protected readonly baseControllerPath: string;
9
+ /**
10
+ * Constructor
11
+ * @param baseControllerPath Base path to API controller
12
+ * @param httpService HTTP service implementation to use for requests
13
+ */
14
+ constructor(baseControllerPath: string, httpService?: IHttpService);
15
+ private readonly _httpService?;
16
+ /**
17
+ * Gets globally selected HTTP service
18
+ */
19
+ protected get httpService(): IHttpService;
20
+ /**
21
+ * Fetches all entities from the read controller.
22
+ * @param {AbortSignal} [signal] - Optional cancellation signal
23
+ * @returns {Promise<ApiSuccessResponseDto<TDto>[], ReadMetadataDto>>} List of all entities with metadata
24
+ */
25
+ readAll(signal?: AbortSignal): Promise<ApiResponseDto<TResultDto[], ReadMetadataDto>>;
26
+ /**
27
+ * Fetches selected entities based on a filter definition.
28
+ * @param {any} definition - The filter definition object
29
+ * @param {AbortSignal} [signal] - Optional cancellation signal
30
+ * @returns {Promise<ApiSuccessResponseDto<TDto>[], ReadMetadataDto>>} The result of the read operation with metadata
31
+ */
32
+ readSelected(definition: ReadSelectedDefinitionDto<TResultDto>, signal?: AbortSignal): Promise<ApiResponseDto<TResultDto[], ReadMetadataDto>>;
33
+ /**
34
+ * Fetches a single entity by its ID.
35
+ * @param {TKey} id - The ID of the entity
36
+ * @param {AbortSignal} [signal] - Optional cancellation signal
37
+ * @returns {Promise<ApiSuccessResponseDto<TDto, EmptyMetadataDto>>} The requested entity
38
+ */
39
+ readSingle(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<TSingleResultDto, EmptyMetadataDto>>;
40
+ }
@@ -0,0 +1,59 @@
1
+ import { beforeEach, describe, expect, it } from 'vitest';
2
+ import { ApiReadControllerClient } from '.';
3
+ import { FetchHttpService } from '../HttpService';
4
+ import { ReadSelectedComparisonOperator, ReadSelectedLogicalOperator, ReadSelectedPropertyType } from '../../../data';
5
+ describe('ApiReadControllerClient', () => {
6
+ let client;
7
+ let fetchService;
8
+ beforeEach(() => {
9
+ fetchService = new FetchHttpService();
10
+ client = new ApiReadControllerClient('/VehiclesSlim', fetchService);
11
+ });
12
+ it('should use injected HTTP service for readAll', async () => {
13
+ const result = (await client.readAll());
14
+ expect(result.ok).toBe(true);
15
+ expect(result.result).toBeDefined();
16
+ });
17
+ it('should use injected HTTP service for readSingle', async () => {
18
+ const testId = 1;
19
+ const result = (await client.readSingle(testId));
20
+ expect(result.ok).toBe(true);
21
+ expect(result.result).toBeDefined();
22
+ expect(typeof result.result).toBe('object');
23
+ expect(result.result.id).toBe(testId);
24
+ });
25
+ it('should use injected HTTP service for readSelected', async () => {
26
+ const definition = {
27
+ searchDefinition: {
28
+ searches: [
29
+ {
30
+ propertyCriteria: [
31
+ {
32
+ propertyName: 'Brand',
33
+ comparisonOperator: ReadSelectedComparisonOperator.Equal,
34
+ valueType: ReadSelectedPropertyType.String,
35
+ value: 'Audi',
36
+ },
37
+ {
38
+ propertyName: 'Brand',
39
+ comparisonOperator: ReadSelectedComparisonOperator.Equal,
40
+ valueType: ReadSelectedPropertyType.String,
41
+ value: 'BMW',
42
+ },
43
+ ],
44
+ logicalOperator: ReadSelectedLogicalOperator.Or,
45
+ },
46
+ ],
47
+ logicalOperator: ReadSelectedLogicalOperator.And,
48
+ },
49
+ };
50
+ const result = (await client.readSelected(definition));
51
+ expect(result.ok).toBe(true);
52
+ expect(result.result).toBeDefined();
53
+ });
54
+ it('should handle HTTP errors properly', async () => {
55
+ const invalidClient = new ApiReadControllerClient('/InvalidPath', fetchService);
56
+ const result = await invalidClient.readAll();
57
+ expect(result.ok).toBe(false);
58
+ });
59
+ });