@blueprint-ts/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/.editorconfig +508 -0
  2. package/.eslintrc.cjs +15 -0
  3. package/.prettierrc.json +8 -0
  4. package/LICENSE +21 -0
  5. package/README.md +1 -0
  6. package/docker-compose.yaml +8 -0
  7. package/docs/.vitepress/config.ts +68 -0
  8. package/docs/.vitepress/theme/Layout.vue +14 -0
  9. package/docs/.vitepress/theme/components/VersionSelector.vue +64 -0
  10. package/docs/.vitepress/theme/index.js +13 -0
  11. package/docs/index.md +70 -0
  12. package/docs/services/laravel/pagination.md +54 -0
  13. package/docs/services/laravel/requests.md +62 -0
  14. package/docs/services/requests/index.md +74 -0
  15. package/docs/vue/forms.md +326 -0
  16. package/docs/vue/requests/route-model-binding.md +66 -0
  17. package/docs/vue/state.md +293 -0
  18. package/env.d.ts +1 -0
  19. package/eslint.config.js +15 -0
  20. package/examples/files/7z2404-x64.exe +0 -0
  21. package/examples/index.html +14 -0
  22. package/examples/js/app.js +8 -0
  23. package/examples/js/router.js +22 -0
  24. package/examples/js/view/App.vue +49 -0
  25. package/examples/js/view/layout/DemoPage.vue +28 -0
  26. package/examples/js/view/pagination/Pagination.vue +28 -0
  27. package/examples/js/view/pagination/components/errorPagination/ErrorPagination.vue +71 -0
  28. package/examples/js/view/pagination/components/errorPagination/GetProductsRequest.ts +54 -0
  29. package/examples/js/view/pagination/components/infiniteScrolling/GetProductsRequest.ts +50 -0
  30. package/examples/js/view/pagination/components/infiniteScrolling/InfiniteScrolling.vue +57 -0
  31. package/examples/js/view/pagination/components/tablePagination/GetProductsRequest.ts +50 -0
  32. package/examples/js/view/pagination/components/tablePagination/TablePagination.vue +63 -0
  33. package/examples/js/view/requests/Requests.vue +34 -0
  34. package/examples/js/view/requests/components/abortableRequest/AbortableRequest.vue +36 -0
  35. package/examples/js/view/requests/components/abortableRequest/GetProductsRequest.ts +25 -0
  36. package/examples/js/view/requests/components/fileDownloadRequest/DownloadFileRequest.ts +15 -0
  37. package/examples/js/view/requests/components/fileDownloadRequest/FileDownloadRequest.vue +44 -0
  38. package/examples/js/view/requests/components/getRequestWithDynamicParams/GetProductsRequest.ts +34 -0
  39. package/examples/js/view/requests/components/getRequestWithDynamicParams/GetRequestWithDynamicParams.vue +59 -0
  40. package/examples/js/view/requests/components/serverErrorRequest/ServerErrorRequest.ts +21 -0
  41. package/examples/js/view/requests/components/serverErrorRequest/ServerErrorRequest.vue +53 -0
  42. package/package.json +81 -0
  43. package/release-tool.json +7 -0
  44. package/src/helpers.ts +78 -0
  45. package/src/service/bulkRequests/BulkRequestEvent.enum.ts +4 -0
  46. package/src/service/bulkRequests/BulkRequestSender.ts +184 -0
  47. package/src/service/bulkRequests/BulkRequestWrapper.ts +49 -0
  48. package/src/service/bulkRequests/index.ts +6 -0
  49. package/src/service/laravel/pagination/contracts/PaginationParamsContract.ts +4 -0
  50. package/src/service/laravel/pagination/contracts/PaginationResponseBodyContract.ts +6 -0
  51. package/src/service/laravel/pagination/dataDrivers/RequestDriver.ts +32 -0
  52. package/src/service/laravel/pagination/index.ts +7 -0
  53. package/src/service/laravel/requests/JsonBaseRequest.ts +35 -0
  54. package/src/service/laravel/requests/PaginationJsonBaseRequest.ts +29 -0
  55. package/src/service/laravel/requests/index.ts +9 -0
  56. package/src/service/laravel/requests/responses/JsonResponse.ts +8 -0
  57. package/src/service/laravel/requests/responses/PaginationResponse.ts +16 -0
  58. package/src/service/pagination/InfiniteScroller.ts +21 -0
  59. package/src/service/pagination/Paginator.ts +149 -0
  60. package/src/service/pagination/contracts/PaginateableRequestContract.ts +13 -0
  61. package/src/service/pagination/contracts/PaginationDataDriverContract.ts +5 -0
  62. package/src/service/pagination/contracts/PaginationResponseContract.ts +7 -0
  63. package/src/service/pagination/contracts/PaginatorLoadDataOptions.ts +4 -0
  64. package/src/service/pagination/contracts/ViewDriverContract.ts +12 -0
  65. package/src/service/pagination/contracts/ViewDriverFactoryContract.ts +5 -0
  66. package/src/service/pagination/dataDrivers/ArrayDriver.ts +28 -0
  67. package/src/service/pagination/dtos/PaginationDataDto.ts +14 -0
  68. package/src/service/pagination/factories/VuePaginationDriverFactory.ts +9 -0
  69. package/src/service/pagination/frontendDrivers/VuePaginationDriver.ts +61 -0
  70. package/src/service/pagination/index.ts +16 -0
  71. package/src/service/persistenceDrivers/LocalStorageDriver.ts +22 -0
  72. package/src/service/persistenceDrivers/NonPersistentDriver.ts +12 -0
  73. package/src/service/persistenceDrivers/SessionStorageDriver.ts +22 -0
  74. package/src/service/persistenceDrivers/index.ts +8 -0
  75. package/src/service/persistenceDrivers/types/PersistenceDriver.ts +5 -0
  76. package/src/service/requests/BaseRequest.ts +197 -0
  77. package/src/service/requests/ErrorHandler.ts +64 -0
  78. package/src/service/requests/RequestEvents.enum.ts +3 -0
  79. package/src/service/requests/RequestMethod.enum.ts +8 -0
  80. package/src/service/requests/bodies/FormDataBody.ts +41 -0
  81. package/src/service/requests/bodies/JsonBody.ts +16 -0
  82. package/src/service/requests/contracts/AbortableRequestContract.ts +3 -0
  83. package/src/service/requests/contracts/BaseRequestContract.ts +36 -0
  84. package/src/service/requests/contracts/BodyContract.ts +7 -0
  85. package/src/service/requests/contracts/BodyFactoryContract.ts +5 -0
  86. package/src/service/requests/contracts/DriverConfigContract.ts +7 -0
  87. package/src/service/requests/contracts/HeadersContract.ts +5 -0
  88. package/src/service/requests/contracts/RequestDriverContract.ts +15 -0
  89. package/src/service/requests/contracts/RequestLoaderContract.ts +5 -0
  90. package/src/service/requests/contracts/RequestLoaderFactoryContract.ts +5 -0
  91. package/src/service/requests/contracts/ResponseContract.ts +7 -0
  92. package/src/service/requests/drivers/contracts/ResponseHandlerContract.ts +10 -0
  93. package/src/service/requests/drivers/fetch/FetchDriver.ts +115 -0
  94. package/src/service/requests/drivers/fetch/FetchResponse.ts +30 -0
  95. package/src/service/requests/exceptions/NoResponseReceivedException.ts +3 -0
  96. package/src/service/requests/exceptions/NotFoundException.ts +3 -0
  97. package/src/service/requests/exceptions/PageExpiredException.ts +3 -0
  98. package/src/service/requests/exceptions/ResponseBodyException.ts +15 -0
  99. package/src/service/requests/exceptions/ResponseException.ts +11 -0
  100. package/src/service/requests/exceptions/ServerErrorException.ts +3 -0
  101. package/src/service/requests/exceptions/UnauthorizedException.ts +3 -0
  102. package/src/service/requests/exceptions/ValidationException.ts +3 -0
  103. package/src/service/requests/exceptions/index.ts +19 -0
  104. package/src/service/requests/factories/FormDataFactory.ts +9 -0
  105. package/src/service/requests/factories/JsonBodyFactory.ts +9 -0
  106. package/src/service/requests/index.ts +50 -0
  107. package/src/service/requests/responses/BaseResponse.ts +41 -0
  108. package/src/service/requests/responses/BlobResponse.ts +19 -0
  109. package/src/service/requests/responses/JsonResponse.ts +15 -0
  110. package/src/service/requests/responses/PlainTextResponse.ts +15 -0
  111. package/src/service/support/DeferredPromise.ts +67 -0
  112. package/src/service/support/index.ts +3 -0
  113. package/src/vue/composables/useConfirmDialog.ts +59 -0
  114. package/src/vue/composables/useGlobalCheckbox.ts +145 -0
  115. package/src/vue/composables/useIsEmpty.ts +34 -0
  116. package/src/vue/composables/useIsOpen.ts +37 -0
  117. package/src/vue/composables/useIsOpenFromVar.ts +61 -0
  118. package/src/vue/composables/useModelWrapper.ts +24 -0
  119. package/src/vue/composables/useOnOpen.ts +34 -0
  120. package/src/vue/contracts/ModelValueOptions.ts +3 -0
  121. package/src/vue/contracts/ModelValueProps.ts +3 -0
  122. package/src/vue/forms/BaseForm.ts +1074 -0
  123. package/src/vue/forms/PropertyAwareArray.ts +78 -0
  124. package/src/vue/forms/index.ts +11 -0
  125. package/src/vue/forms/types/PersistedForm.ts +6 -0
  126. package/src/vue/forms/validation/ValidationMode.enum.ts +14 -0
  127. package/src/vue/forms/validation/index.ts +12 -0
  128. package/src/vue/forms/validation/rules/BaseRule.ts +7 -0
  129. package/src/vue/forms/validation/rules/ConfirmedRule.ts +39 -0
  130. package/src/vue/forms/validation/rules/MinRule.ts +61 -0
  131. package/src/vue/forms/validation/rules/RequiredRule.ts +19 -0
  132. package/src/vue/forms/validation/rules/UrlRule.ts +24 -0
  133. package/src/vue/forms/validation/types/BidirectionalRule.ts +11 -0
  134. package/src/vue/index.ts +14 -0
  135. package/src/vue/requests/factories/VueRequestLoaderFactory.ts +9 -0
  136. package/src/vue/requests/index.ts +5 -0
  137. package/src/vue/requests/loaders/VueRequestBatchLoader.ts +30 -0
  138. package/src/vue/requests/loaders/VueRequestLoader.ts +18 -0
  139. package/src/vue/router/routeModelBinding/RouteModelRequestResolver.ts +11 -0
  140. package/src/vue/router/routeModelBinding/defineRoute.ts +31 -0
  141. package/src/vue/router/routeModelBinding/index.ts +8 -0
  142. package/src/vue/router/routeModelBinding/installRouteInjection.ts +73 -0
  143. package/src/vue/router/routeModelBinding/types.ts +46 -0
  144. package/src/vue/state/State.ts +391 -0
  145. package/src/vue/state/index.ts +3 -0
  146. package/tests/service/helpers/mergeDeep.test.ts +53 -0
  147. package/tests/service/laravel/pagination/dataDrivers/RequestDriver.test.ts +84 -0
  148. package/tests/service/laravel/requests/JsonBaseRequest.test.ts +43 -0
  149. package/tests/service/laravel/requests/PaginationJsonBaseRequest.test.ts +58 -0
  150. package/tests/service/laravel/requests/responses/JsonResponse.test.ts +59 -0
  151. package/tests/service/laravel/requests/responses/PaginationResponse.test.ts +127 -0
  152. package/tests/service/pagination/dtos/PaginationDataDto.test.ts +35 -0
  153. package/tests/service/pagination/factories/VuePaginationDriverFactory.test.ts +32 -0
  154. package/tests/service/pagination/frontendDrivers/VuePaginationDriver.test.ts +66 -0
  155. package/tests/service/requests/ErrorHandler.test.ts +141 -0
  156. package/tsconfig.json +114 -0
  157. package/vite.config.ts +34 -0
  158. package/vitest.config.ts +14 -0
@@ -0,0 +1,5 @@
1
+ import { type RequestLoaderContract } from './RequestLoaderContract'
2
+
3
+ export interface RequestLoaderFactoryContract<T> {
4
+ make(): RequestLoaderContract<T>
5
+ }
@@ -0,0 +1,7 @@
1
+ import type { ResponseHandlerContract } from '../drivers/contracts/ResponseHandlerContract'
2
+
3
+ export interface ResponseContract<ResponseBodyInterface> {
4
+ getAcceptHeader(): string
5
+
6
+ setResponse(response: ResponseHandlerContract): Promise<ResponseBodyInterface>
7
+ }
@@ -0,0 +1,10 @@
1
+ import { type HeadersContract } from '../../contracts/HeadersContract'
2
+
3
+ export interface ResponseHandlerContract {
4
+ getStatusCode(): number | undefined
5
+ getHeaders(): HeadersContract
6
+ getRawResponse(): Response
7
+ json<ResponseBodyInterface>(): Promise<ResponseBodyInterface>
8
+ text(): Promise<string>
9
+ blob(): Promise<Blob>
10
+ }
@@ -0,0 +1,115 @@
1
+ import { ResponseException } from '../../exceptions/ResponseException'
2
+ import { FetchResponse } from './FetchResponse'
3
+ import { RequestMethodEnum } from '../../RequestMethod.enum'
4
+ import { type HeadersContract, type HeaderValue } from '../../contracts/HeadersContract'
5
+ import { type BodyContract } from '../../contracts/BodyContract'
6
+ import { type RequestDriverContract } from '../../contracts/RequestDriverContract'
7
+ import { type DriverConfigContract } from '../../contracts/DriverConfigContract'
8
+ import { type ResponseHandlerContract } from '../contracts/ResponseHandlerContract'
9
+
10
+ enum FetchDriverCredentialConfigEnum {
11
+ OMIT = 'omit',
12
+ INCLUDE = 'include'
13
+ }
14
+
15
+ interface FetchDriverConfig {
16
+ method: RequestMethodEnum
17
+ headers: HeadersContract
18
+ credentials?: FetchDriverCredentialConfigEnum | undefined
19
+ signal?: AbortSignal | undefined
20
+ body?: string | FormData | Blob | ArrayBuffer | ArrayBufferView | URLSearchParams | undefined
21
+ }
22
+
23
+ export class FetchDriver implements RequestDriverContract {
24
+ public constructor(protected config?: DriverConfigContract) {}
25
+
26
+ public async send(
27
+ url: URL | string,
28
+ method: RequestMethodEnum,
29
+ headers: HeadersContract,
30
+ body?: BodyContract,
31
+ requestConfig?: DriverConfigContract
32
+ ): Promise<ResponseHandlerContract> {
33
+ const mergedConfig: DriverConfigContract = {
34
+ // Global config
35
+ ...this.config,
36
+
37
+ // Request specific overrides
38
+ ...(requestConfig ?? {})
39
+ }
40
+
41
+ const mergedHeaders: HeadersContract = {
42
+ // Set global headers
43
+ ...this.config?.headers,
44
+
45
+ // Set headers from the request
46
+ ...headers,
47
+
48
+ // Set Content-Type header
49
+ ...body?.getHeaders()
50
+ }
51
+
52
+ const resolvedHeaders = this.resolveHeaders(mergedHeaders)
53
+
54
+ const fetchConfig = this.buildRequestConfig(mergedConfig, method, resolvedHeaders, body)
55
+
56
+ const response = await fetch(url, fetchConfig as RequestInit)
57
+
58
+ const fetchResponse = new FetchResponse(response)
59
+
60
+ if (!response.ok) {
61
+ throw new ResponseException(fetchResponse)
62
+ }
63
+
64
+ return fetchResponse
65
+ }
66
+
67
+ protected buildRequestConfig(
68
+ config: DriverConfigContract,
69
+ method: RequestMethodEnum,
70
+ headers: HeadersContract,
71
+ body?: BodyContract
72
+ ): FetchDriverConfig {
73
+ return {
74
+ method: method,
75
+ headers: headers,
76
+ credentials: this.getCorsWithCredentials(config.corsWithCredentials),
77
+ signal: config.abortSignal ?? undefined,
78
+ body: [RequestMethodEnum.GET, RequestMethodEnum.HEAD].includes(method) ? undefined : body?.getContent()
79
+ }
80
+ }
81
+
82
+ protected getCorsWithCredentials(corsWithCredentials: boolean | undefined): FetchDriverCredentialConfigEnum {
83
+ // Request takes precedence
84
+ if (corsWithCredentials === true) {
85
+ return FetchDriverCredentialConfigEnum.INCLUDE
86
+ }
87
+
88
+ if (corsWithCredentials === false) {
89
+ return FetchDriverCredentialConfigEnum.OMIT
90
+ }
91
+
92
+ // Fallback to default config
93
+ if (this.config) {
94
+ return this.config.corsWithCredentials ? FetchDriverCredentialConfigEnum.INCLUDE : FetchDriverCredentialConfigEnum.OMIT
95
+ }
96
+
97
+ // Fallback to safe option if no default set
98
+ return FetchDriverCredentialConfigEnum.OMIT
99
+ }
100
+
101
+ protected resolveHeaders(headers: HeadersContract): HeadersContract {
102
+ const resolved: HeadersContract = {}
103
+ for (const key in headers) {
104
+ const value: HeaderValue | undefined = headers[key]
105
+
106
+ if (value === undefined) {
107
+ continue
108
+ }
109
+
110
+ resolved[key] = typeof value === 'function' ? value() : value
111
+ }
112
+
113
+ return resolved
114
+ }
115
+ }
@@ -0,0 +1,30 @@
1
+ import { type HeadersContract } from '../../contracts/HeadersContract'
2
+ import { type ResponseHandlerContract } from '../contracts/ResponseHandlerContract'
3
+
4
+ export class FetchResponse implements ResponseHandlerContract {
5
+ public constructor(protected response: Response) {}
6
+
7
+ public getStatusCode(): number | undefined {
8
+ return this.response.status
9
+ }
10
+
11
+ public getHeaders(): HeadersContract {
12
+ return Object.fromEntries(this.response.headers)
13
+ }
14
+
15
+ public getRawResponse(): Response {
16
+ return this.response
17
+ }
18
+
19
+ public async json<ResponseBodyInterface>(): Promise<ResponseBodyInterface> {
20
+ return await this.response.json()
21
+ }
22
+
23
+ public async text(): Promise<string> {
24
+ return await this.response.text()
25
+ }
26
+
27
+ public async blob(): Promise<Blob> {
28
+ return await this.response.blob()
29
+ }
30
+ }
@@ -0,0 +1,3 @@
1
+ import { ResponseException } from './ResponseException'
2
+
3
+ export class NoResponseReceivedException extends ResponseException {}
@@ -0,0 +1,3 @@
1
+ import { ResponseBodyException } from './ResponseBodyException'
2
+
3
+ export class NotFoundException<ResponseErrorBody> extends ResponseBodyException<ResponseErrorBody> {}
@@ -0,0 +1,3 @@
1
+ import { ResponseBodyException } from './ResponseBodyException'
2
+
3
+ export class PageExpiredException<ResponseErrorBody> extends ResponseBodyException<ResponseErrorBody> {}
@@ -0,0 +1,15 @@
1
+ import { ResponseException } from './ResponseException'
2
+ import { type ResponseHandlerContract } from '../drivers/contracts/ResponseHandlerContract'
3
+
4
+ export class ResponseBodyException<ResponseErrorBody> extends ResponseException {
5
+ public constructor(
6
+ response: ResponseHandlerContract,
7
+ protected body: ResponseErrorBody
8
+ ) {
9
+ super(response)
10
+ }
11
+
12
+ public getBody(): ResponseErrorBody {
13
+ return this.body
14
+ }
15
+ }
@@ -0,0 +1,11 @@
1
+ import { type ResponseHandlerContract } from '../drivers/contracts/ResponseHandlerContract'
2
+
3
+ export class ResponseException extends Error {
4
+ constructor(protected response: ResponseHandlerContract) {
5
+ super()
6
+ }
7
+
8
+ public getResponse(): ResponseHandlerContract {
9
+ return this.response
10
+ }
11
+ }
@@ -0,0 +1,3 @@
1
+ import { ResponseBodyException } from './ResponseBodyException'
2
+
3
+ export class ServerErrorException<ResponseErrorBody> extends ResponseBodyException<ResponseErrorBody> {}
@@ -0,0 +1,3 @@
1
+ import { ResponseBodyException } from './ResponseBodyException'
2
+
3
+ export class UnauthorizedException<ResponseErrorBody> extends ResponseBodyException<ResponseErrorBody> {}
@@ -0,0 +1,3 @@
1
+ import { ResponseBodyException } from './ResponseBodyException'
2
+
3
+ export class ValidationException<ResponseErrorBody> extends ResponseBodyException<ResponseErrorBody> {}
@@ -0,0 +1,19 @@
1
+ import { ValidationException } from './ValidationException'
2
+ import { NotFoundException } from './NotFoundException'
3
+ import { NoResponseReceivedException } from './NoResponseReceivedException'
4
+ import { UnauthorizedException } from './UnauthorizedException'
5
+ import { PageExpiredException } from './PageExpiredException'
6
+ import { ServerErrorException } from './ServerErrorException'
7
+ import { ResponseException } from './ResponseException'
8
+ import { ResponseBodyException } from './ResponseBodyException'
9
+
10
+ export {
11
+ ValidationException,
12
+ NotFoundException,
13
+ NoResponseReceivedException,
14
+ UnauthorizedException,
15
+ PageExpiredException,
16
+ ServerErrorException,
17
+ ResponseException,
18
+ ResponseBodyException
19
+ }
@@ -0,0 +1,9 @@
1
+ import { FormDataBody } from '../bodies/FormDataBody'
2
+ import { type BodyFactoryContract } from '../contracts/BodyFactoryContract'
3
+ import { type BodyContract } from '../contracts/BodyContract'
4
+
5
+ export class FormDataFactory<RequestBodyInterface> implements BodyFactoryContract<RequestBodyInterface> {
6
+ public make(body: RequestBodyInterface): BodyContract {
7
+ return new FormDataBody<RequestBodyInterface>(body)
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ import { JsonBody } from '../bodies/JsonBody'
2
+ import { type BodyFactoryContract } from '../contracts/BodyFactoryContract'
3
+ import { type BodyContract } from '../contracts/BodyContract'
4
+
5
+ export class JsonBodyFactory<RequestBodyInterface> implements BodyFactoryContract<RequestBodyInterface> {
6
+ public make(body: RequestBodyInterface): BodyContract {
7
+ return new JsonBody<RequestBodyInterface>(body)
8
+ }
9
+ }
@@ -0,0 +1,50 @@
1
+ import { FetchDriver } from './drivers/fetch/FetchDriver'
2
+ import { BaseResponse } from './responses/BaseResponse'
3
+ import { JsonResponse } from './responses/JsonResponse'
4
+ import { PlainTextResponse } from './responses/PlainTextResponse'
5
+ import { BlobResponse } from './responses/BlobResponse'
6
+ import { BaseRequest } from './BaseRequest'
7
+ import { ErrorHandler } from './ErrorHandler'
8
+ import { RequestEvents } from './RequestEvents.enum'
9
+ import { RequestMethodEnum } from './RequestMethod.enum'
10
+ import { JsonBodyFactory } from './factories/JsonBodyFactory'
11
+ import { FormDataFactory } from './factories/FormDataFactory'
12
+ import { type BodyContract } from './contracts/BodyContract'
13
+ import { type RequestLoaderContract } from './contracts/RequestLoaderContract'
14
+ import { type RequestDriverContract } from './contracts/RequestDriverContract'
15
+ import { type PaginationParamsContract } from '../laravel/pagination/contracts/PaginationParamsContract'
16
+ import { type RequestLoaderFactoryContract } from './contracts/RequestLoaderFactoryContract'
17
+ import { type DriverConfigContract } from './contracts/DriverConfigContract'
18
+ import { type BodyFactoryContract } from './contracts/BodyFactoryContract'
19
+ import { type ResponseHandlerContract } from './drivers/contracts/ResponseHandlerContract'
20
+ import { type BaseRequestContract } from './contracts/BaseRequestContract'
21
+ import { ResponseException } from './exceptions/ResponseException'
22
+ import { type HeadersContract } from './contracts/HeadersContract'
23
+
24
+ export {
25
+ FetchDriver,
26
+ BaseResponse,
27
+ JsonResponse,
28
+ BlobResponse,
29
+ PlainTextResponse,
30
+ BaseRequest,
31
+ ErrorHandler,
32
+ RequestEvents,
33
+ RequestMethodEnum,
34
+ ResponseException,
35
+ JsonBodyFactory,
36
+ FormDataFactory
37
+ }
38
+
39
+ export type {
40
+ PaginationParamsContract,
41
+ RequestDriverContract,
42
+ RequestLoaderContract,
43
+ BodyContract,
44
+ RequestLoaderFactoryContract,
45
+ DriverConfigContract,
46
+ BodyFactoryContract,
47
+ ResponseHandlerContract,
48
+ BaseRequestContract,
49
+ HeadersContract
50
+ }
@@ -0,0 +1,41 @@
1
+ import { type ResponseHandlerContract } from '../drivers/contracts/ResponseHandlerContract'
2
+ import { type HeadersContract } from '../contracts/HeadersContract'
3
+ import { type ResponseContract } from '../contracts/ResponseContract'
4
+
5
+ export abstract class BaseResponse<ResponseInterface> implements ResponseContract<ResponseInterface> {
6
+ private body?: ResponseInterface
7
+
8
+ protected response?: ResponseHandlerContract
9
+
10
+ public abstract getAcceptHeader(): string
11
+
12
+ protected abstract resolveBody(): Promise<ResponseInterface>
13
+
14
+ public async setResponse(response: ResponseHandlerContract): Promise<ResponseInterface> {
15
+ this.response = response
16
+
17
+ this.body = await this.resolveBody()
18
+
19
+ return this.body
20
+ }
21
+
22
+ public getRawResponse(): Response | undefined {
23
+ return this.response?.getRawResponse()
24
+ }
25
+
26
+ public getStatusCode(): number | undefined {
27
+ return this.response?.getStatusCode()
28
+ }
29
+
30
+ public getHeaders(): HeadersContract | undefined {
31
+ return this.response?.getHeaders()
32
+ }
33
+
34
+ public getBody(): ResponseInterface {
35
+ if (this.body === undefined) {
36
+ throw new Error('Response body is not set')
37
+ }
38
+
39
+ return this.body
40
+ }
41
+ }
@@ -0,0 +1,19 @@
1
+ import { BaseResponse } from './BaseResponse'
2
+
3
+ export class BlobResponse extends BaseResponse<Blob> {
4
+ public constructor(protected mimeType: string = 'application/octet-stream') {
5
+ super()
6
+ }
7
+
8
+ public getAcceptHeader(): string {
9
+ return this.mimeType
10
+ }
11
+
12
+ protected resolveBody(): Promise<Blob> {
13
+ if (!this.response) {
14
+ throw new Error('Response is not set')
15
+ }
16
+
17
+ return this.response.blob()
18
+ }
19
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseResponse } from './BaseResponse'
2
+
3
+ export class JsonResponse<ResponseBodyInterface> extends BaseResponse<ResponseBodyInterface> {
4
+ public getAcceptHeader(): string {
5
+ return 'application/json'
6
+ }
7
+
8
+ protected resolveBody(): Promise<ResponseBodyInterface> {
9
+ if (!this.response) {
10
+ throw new Error('Response is not set')
11
+ }
12
+
13
+ return this.response.json<ResponseBodyInterface>()
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseResponse } from './BaseResponse'
2
+
3
+ export class PlainTextResponse extends BaseResponse<string> {
4
+ public getAcceptHeader(): string {
5
+ return 'text/plain'
6
+ }
7
+
8
+ protected resolveBody(): Promise<string> {
9
+ if (!this.response) {
10
+ throw new Error('Response is not set')
11
+ }
12
+
13
+ return this.response.text()
14
+ }
15
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * A new instance of deferred is constructed by calling `new DeferredPromse<T>()`.
3
+ * The purpose of the deferred object is to expose the associated Promise
4
+ * instance APIs that can be used for signaling the successful
5
+ * or unsuccessful completion, as well as the state of the task.
6
+ * @export
7
+ * @class DeferredPromise
8
+ * @implements {Promise<T>}
9
+ * @template T
10
+ * @example
11
+ * const deferred = new DeferredPromse<string>();
12
+ * console.log(deferred.state); // 'pending'
13
+ *
14
+ * deferred
15
+ * .then(str => console.log(str))
16
+ * .catch(err => console.error(err));
17
+ *
18
+ * deferred.resolve('Foo');
19
+ * console.log(deferred.state); // 'fulfilled'
20
+ * // deferred.reject('Bar');
21
+ *
22
+ * https://gist.github.com/GFoley83/5877f6c09fbcfd62569c51dc91444cf0
23
+ */
24
+ export class DeferredPromise<T> implements Promise<T> {
25
+ readonly [Symbol.toStringTag]: 'Promise' = 'Promise'
26
+
27
+ private _promise: Promise<T>
28
+ private _resolve!: (value: T | PromiseLike<T>) => void
29
+ private _reject!: (reason?: unknown) => void
30
+ private _state: 'pending' | 'fulfilled' | 'rejected' = 'pending'
31
+
32
+ public get state(): 'pending' | 'fulfilled' | 'rejected' {
33
+ return this._state
34
+ }
35
+
36
+ public constructor() {
37
+ this._promise = new Promise<T>((resolve, reject) => {
38
+ this._resolve = resolve
39
+ this._reject = reject
40
+ })
41
+ }
42
+
43
+ public then<TResult1 = T, TResult2 = never>(
44
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
45
+ onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null
46
+ ): Promise<TResult1 | TResult2> {
47
+ return this._promise.then(onfulfilled, onrejected)
48
+ }
49
+
50
+ public catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult> {
51
+ return this._promise.catch(onrejected)
52
+ }
53
+
54
+ public finally(onfinally?: (() => void) | null): Promise<T> {
55
+ return this._promise.finally(onfinally)
56
+ }
57
+
58
+ public resolve(value: T | PromiseLike<T>): void {
59
+ this._resolve(value)
60
+ this._state = 'fulfilled'
61
+ }
62
+
63
+ public reject(reason?: unknown): void {
64
+ this._reject(reason)
65
+ this._state = 'rejected'
66
+ }
67
+ }
@@ -0,0 +1,3 @@
1
+ import { DeferredPromise } from './DeferredPromise'
2
+
3
+ export { DeferredPromise }
@@ -0,0 +1,59 @@
1
+ import { getCurrentInstance, h, onUnmounted, render } from 'vue'
2
+ import { type Component } from 'vue'
3
+
4
+ export type ConfirmDialogSeverity = 'info' | 'warning' | 'danger'
5
+
6
+ export interface ConfirmDialogOptions {
7
+ getMessage(): string
8
+
9
+ getSeverity(): ConfirmDialogSeverity
10
+
11
+ getTitle(): string
12
+
13
+ getOkText(): string
14
+
15
+ getCancelText(): string
16
+ }
17
+
18
+ /**
19
+ * The provided component needs to expose an "open" method, which
20
+ * should return a promise resolving into true or false.
21
+ */
22
+ export default function (confirmDialogComponent: Component, querySelector: string = 'body') {
23
+ const self = getCurrentInstance()
24
+
25
+ /**
26
+ * https://stackoverflow.com/a/78448128
27
+ */
28
+ function mountConfirmDialog(options: ConfirmDialogOptions) {
29
+ if (!self?.appContext) {
30
+ throw new Error('ConfirmationDialog: useConfirmDialog must be called inside a setup function')
31
+ }
32
+
33
+ const vNode = h(confirmDialogComponent, { options })
34
+ vNode.key = Symbol()
35
+ vNode.appContext = self.appContext
36
+ render(vNode, document.querySelector(querySelector) as Element)
37
+ return vNode.component
38
+ }
39
+
40
+ function unmountConfirmDialog() {
41
+ render(null, document.querySelector(querySelector) as Element)
42
+ }
43
+
44
+ onUnmounted(() => {
45
+ unmountConfirmDialog()
46
+ })
47
+
48
+ async function openConfirmDialog(options: ConfirmDialogOptions): Promise<boolean> {
49
+ const dialogComponent = mountConfirmDialog(options)
50
+
51
+ if (dialogComponent?.exposed == undefined || dialogComponent?.exposed['open'] === undefined) {
52
+ throw new Error('ConfirmationDialog: Provided component does not expose an "open" method')
53
+ }
54
+
55
+ return dialogComponent?.exposed['open']
56
+ }
57
+
58
+ return { openConfirmDialog }
59
+ }