@ethlete/query 5.15.0 → 5.16.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.
- package/.eslintrc.json +40 -0
- package/CHANGELOG.md +14 -0
- package/jest.config.ts +23 -0
- package/ng-package.json +8 -0
- package/package.json +6 -23
- package/project.json +37 -0
- package/{index.d.ts → src/index.ts} +2 -0
- package/src/lib/auth/auth-provider.types.ts +160 -0
- package/src/lib/auth/auth-provider.utils.ts +39 -0
- package/src/lib/auth/basic-auth-provider.ts +17 -0
- package/src/lib/auth/bearer-auth-provider.ts +243 -0
- package/src/lib/auth/custom-header-auth-provider.ts +13 -0
- package/{lib/class-validator/class-validator.types.d.ts → src/lib/class-validator/class-validator.types.ts} +4 -3
- package/src/lib/class-validator/class-validator.utils.ts +5 -0
- package/src/lib/devtools/components/query-devtools/query-devtools.component.html +402 -0
- package/src/lib/devtools/components/query-devtools/query-devtools.component.scss +360 -0
- package/src/lib/devtools/components/query-devtools/query-devtools.component.ts +427 -0
- package/src/lib/devtools/pipes/query-short-name.pipe.ts +24 -0
- package/src/lib/devtools/utils/query-client.utils.ts +25 -0
- package/src/lib/directives/infinity-query-trigger.directive.ts +58 -0
- package/src/lib/directives/infinity-query.directive.ts +208 -0
- package/src/lib/directives/query.directive.ts +201 -0
- package/src/lib/entity/entity-store.ts +180 -0
- package/src/lib/entity/entity.types.ts +34 -0
- package/src/lib/entity/entity.utils.ts +51 -0
- package/src/lib/gql/gql.ts +22 -0
- package/src/lib/infinite-query/infinity-query.ts +245 -0
- package/src/lib/infinite-query/infinity-query.types.ts +149 -0
- package/src/lib/infinite-query/infinity-query.utils.ts +14 -0
- package/src/lib/logger/logger.ts +30 -0
- package/src/lib/query/query.ts +631 -0
- package/src/lib/query/query.types.ts +532 -0
- package/src/lib/query/query.utils.spec.ts +92 -0
- package/src/lib/query/query.utils.ts +450 -0
- package/src/lib/query-client/query-client.spec.ts +77 -0
- package/src/lib/query-client/query-client.ts +195 -0
- package/src/lib/query-client/query-client.types.ts +101 -0
- package/src/lib/query-client/query-client.utils.spec.ts +61 -0
- package/src/lib/query-client/query-client.utils.ts +28 -0
- package/src/lib/query-creator/query-creator.ts +103 -0
- package/src/lib/query-creator/query-creator.types.ts +74 -0
- package/src/lib/query-form/query-form.ts +526 -0
- package/src/lib/query-form/query-form.types.ts +169 -0
- package/src/lib/query-form/query-form.utils.ts +116 -0
- package/src/lib/query-store/query-store.ts +192 -0
- package/src/lib/request/request.ts +253 -0
- package/src/lib/request/request.types.ts +164 -0
- package/src/lib/request/request.util.spec.ts +177 -0
- package/src/lib/request/request.util.ts +399 -0
- package/src/lib/stories/angular-example-page.mdx +85 -0
- package/src/lib/stories/authentication-page.mdx +35 -0
- package/src/lib/stories/changelog-page.mdx +9 -0
- package/src/lib/stories/client-page.mdx +100 -0
- package/src/lib/stories/queries-page.mdx +117 -0
- package/src/lib/symfony/symfony.types.ts +21 -0
- package/src/lib/symfony/symfony.utils.ts +43 -0
- package/src/lib/utils/data.utils.ts +280 -0
- package/src/lib/utils/deep-freeze.util.ts +21 -0
- package/{lib/utils/def.util.d.ts → src/lib/utils/def.util.ts} +1 -1
- package/src/test-setup.ts +1 -0
- package/tsconfig.json +29 -0
- package/tsconfig.lib.json +12 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +11 -0
- package/esm2022/ethlete-query.mjs +0 -5
- package/esm2022/index.mjs +0 -20
- package/esm2022/lib/auth/auth-provider.types.mjs +0 -2
- package/esm2022/lib/auth/auth-provider.utils.mjs +0 -25
- package/esm2022/lib/auth/basic-auth-provider.mjs +0 -15
- package/esm2022/lib/auth/bearer-auth-provider.mjs +0 -168
- package/esm2022/lib/auth/custom-header-auth-provider.mjs +0 -12
- package/esm2022/lib/auth/index.mjs +0 -6
- package/esm2022/lib/class-validator/class-validator.types.mjs +0 -2
- package/esm2022/lib/class-validator/class-validator.utils.mjs +0 -4
- package/esm2022/lib/class-validator/index.mjs +0 -3
- package/esm2022/lib/devtools/components/query-devtools/index.mjs +0 -2
- package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +0 -297
- package/esm2022/lib/devtools/pipes/index.mjs +0 -2
- package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +0 -24
- package/esm2022/lib/devtools/utils/index.mjs +0 -2
- package/esm2022/lib/devtools/utils/query-client.utils.mjs +0 -13
- package/esm2022/lib/directives/index.mjs +0 -4
- package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +0 -56
- package/esm2022/lib/directives/infinity-query.directive.mjs +0 -147
- package/esm2022/lib/directives/query.directive.mjs +0 -123
- package/esm2022/lib/entity/entity-store.mjs +0 -127
- package/esm2022/lib/entity/entity.types.mjs +0 -2
- package/esm2022/lib/entity/entity.utils.mjs +0 -29
- package/esm2022/lib/entity/index.mjs +0 -4
- package/esm2022/lib/gql/gql.mjs +0 -23
- package/esm2022/lib/gql/index.mjs +0 -2
- package/esm2022/lib/infinite-query/index.mjs +0 -4
- package/esm2022/lib/infinite-query/infinity-query.mjs +0 -171
- package/esm2022/lib/infinite-query/infinity-query.types.mjs +0 -2
- package/esm2022/lib/infinite-query/infinity-query.utils.mjs +0 -3
- package/esm2022/lib/logger/index.mjs +0 -2
- package/esm2022/lib/logger/logger.mjs +0 -16
- package/esm2022/lib/query/index.mjs +0 -4
- package/esm2022/lib/query/query.mjs +0 -428
- package/esm2022/lib/query/query.types.mjs +0 -2
- package/esm2022/lib/query/query.utils.mjs +0 -253
- package/esm2022/lib/query-client/index.mjs +0 -4
- package/esm2022/lib/query-client/query-client.mjs +0 -80
- package/esm2022/lib/query-client/query-client.types.mjs +0 -2
- package/esm2022/lib/query-client/query-client.utils.mjs +0 -20
- package/esm2022/lib/query-creator/index.mjs +0 -3
- package/esm2022/lib/query-creator/query-creator.mjs +0 -55
- package/esm2022/lib/query-creator/query-creator.types.mjs +0 -2
- package/esm2022/lib/query-form/index.mjs +0 -4
- package/esm2022/lib/query-form/query-form.mjs +0 -368
- package/esm2022/lib/query-form/query-form.types.mjs +0 -2
- package/esm2022/lib/query-form/query-form.utils.mjs +0 -97
- package/esm2022/lib/query-store/index.mjs +0 -2
- package/esm2022/lib/query-store/query-store.mjs +0 -144
- package/esm2022/lib/request/index.mjs +0 -4
- package/esm2022/lib/request/request.mjs +0 -196
- package/esm2022/lib/request/request.types.mjs +0 -2
- package/esm2022/lib/request/request.util.mjs +0 -252
- package/esm2022/lib/symfony/index.mjs +0 -3
- package/esm2022/lib/symfony/symfony.types.mjs +0 -2
- package/esm2022/lib/symfony/symfony.utils.mjs +0 -31
- package/esm2022/lib/utils/data.utils.mjs +0 -138
- package/esm2022/lib/utils/deep-freeze.util.mjs +0 -17
- package/esm2022/lib/utils/def.util.mjs +0 -8
- package/esm2022/lib/utils/index.mjs +0 -4
- package/fesm2022/ethlete-query.mjs +0 -3276
- package/fesm2022/ethlete-query.mjs.map +0 -1
- package/lib/auth/auth-provider.types.d.ts +0 -133
- package/lib/auth/auth-provider.utils.d.ts +0 -9
- package/lib/auth/basic-auth-provider.d.ts +0 -10
- package/lib/auth/bearer-auth-provider.d.ts +0 -23
- package/lib/auth/custom-header-auth-provider.d.ts +0 -9
- package/lib/class-validator/class-validator.utils.d.ts +0 -2
- package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +0 -151
- package/lib/devtools/pipes/query-short-name.pipe.d.ts +0 -8
- package/lib/devtools/utils/query-client.utils.d.ts +0 -12
- package/lib/directives/infinity-query-trigger.directive.d.ts +0 -15
- package/lib/directives/infinity-query.directive.d.ts +0 -49
- package/lib/directives/query.directive.d.ts +0 -63
- package/lib/entity/entity-store.d.ts +0 -25
- package/lib/entity/entity.types.d.ts +0 -25
- package/lib/entity/entity.utils.d.ts +0 -12
- package/lib/gql/gql.d.ts +0 -6
- package/lib/infinite-query/infinity-query.d.ts +0 -29
- package/lib/infinite-query/infinity-query.types.d.ts +0 -104
- package/lib/infinite-query/infinity-query.utils.d.ts +0 -4
- package/lib/logger/logger.d.ts +0 -12
- package/lib/query/query.d.ts +0 -60
- package/lib/query/query.types.d.ts +0 -388
- package/lib/query/query.utils.d.ts +0 -91
- package/lib/query-client/query-client.d.ts +0 -29
- package/lib/query-client/query-client.types.d.ts +0 -82
- package/lib/query-client/query-client.utils.d.ts +0 -4
- package/lib/query-creator/query-creator.d.ts +0 -20
- package/lib/query-creator/query-creator.types.d.ts +0 -13
- package/lib/query-form/query-form.d.ts +0 -89
- package/lib/query-form/query-form.types.d.ts +0 -138
- package/lib/query-form/query-form.utils.d.ts +0 -13
- package/lib/query-store/query-store.d.ts +0 -31
- package/lib/request/request.d.ts +0 -3
- package/lib/request/request.types.d.ts +0 -126
- package/lib/request/request.util.d.ts +0 -92
- package/lib/symfony/symfony.types.d.ts +0 -19
- package/lib/symfony/symfony.utils.d.ts +0 -6
- package/lib/utils/data.utils.d.ts +0 -59
- package/lib/utils/deep-freeze.util.d.ts +0 -1
- /package/{lib/auth/index.d.ts → src/lib/auth/index.ts} +0 -0
- /package/{lib/class-validator/index.d.ts → src/lib/class-validator/index.ts} +0 -0
- /package/{lib/devtools/components/query-devtools/index.d.ts → src/lib/devtools/components/query-devtools/index.ts} +0 -0
- /package/{lib/devtools/pipes/index.d.ts → src/lib/devtools/pipes/index.ts} +0 -0
- /package/{lib/devtools/utils/index.d.ts → src/lib/devtools/utils/index.ts} +0 -0
- /package/{lib/directives/index.d.ts → src/lib/directives/index.ts} +0 -0
- /package/{lib/entity/index.d.ts → src/lib/entity/index.ts} +0 -0
- /package/{lib/gql/index.d.ts → src/lib/gql/index.ts} +0 -0
- /package/{lib/infinite-query/index.d.ts → src/lib/infinite-query/index.ts} +0 -0
- /package/{lib/logger/index.d.ts → src/lib/logger/index.ts} +0 -0
- /package/{lib/query/index.d.ts → src/lib/query/index.ts} +0 -0
- /package/{lib/query-client/index.d.ts → src/lib/query-client/index.ts} +0 -0
- /package/{lib/query-creator/index.d.ts → src/lib/query-creator/index.ts} +0 -0
- /package/{lib/query-form/index.d.ts → src/lib/query-form/index.ts} +0 -0
- /package/{lib/query-store/index.d.ts → src/lib/query-store/index.ts} +0 -0
- /package/{lib/request/index.d.ts → src/lib/request/index.ts} +0 -0
- /package/{lib/symfony/index.d.ts → src/lib/symfony/index.ts} +0 -0
- /package/{lib/utils/index.d.ts → src/lib/utils/index.ts} +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="HttpClient/Client" />
|
|
4
|
+
|
|
5
|
+
# HttpClient
|
|
6
|
+
|
|
7
|
+
For API requests, the Eth SDK offers you the option of using a powerful query client. The client includes standard authentication, e.g. with Bearer Token.
|
|
8
|
+
|
|
9
|
+
## Clients
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { QueryClient } from '@ethlete/query';
|
|
13
|
+
|
|
14
|
+
export const client = new QueryClient({
|
|
15
|
+
baseRoute: 'https://api.test.com',
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Options
|
|
20
|
+
|
|
21
|
+
##### Logging
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
export const client = new QueryClient({
|
|
25
|
+
baseRoute: 'https://api.test.com',
|
|
26
|
+
logging: {
|
|
27
|
+
/**
|
|
28
|
+
* Log all query state changes.
|
|
29
|
+
*/
|
|
30
|
+
queryStateChanges?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Log query state garbage collector runs.
|
|
33
|
+
*/
|
|
34
|
+
queryStateGarbageCollector?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Log if subscriptions are made to queries that are in the `prepared` state.
|
|
37
|
+
* This usually indicates that the `.execute()` method was forgotten.
|
|
38
|
+
*/
|
|
39
|
+
preparedQuerySubscriptions?: boolean;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
##### Request
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { QueryClient } from '@ethlete/query';
|
|
50
|
+
|
|
51
|
+
export const client = new QueryClient({
|
|
52
|
+
baseRoute: 'https://api.test.com',
|
|
53
|
+
request?: {
|
|
54
|
+
/**
|
|
55
|
+
* Adapter function used for extracting the time until the response is invalid.
|
|
56
|
+
* The default uses the `cache-control` (`max-age` & `s-maxage`), `age` and `expires` headers.
|
|
57
|
+
* Should return a number in seconds.
|
|
58
|
+
*/
|
|
59
|
+
cacheAdapter?: CacheAdapterFn;
|
|
60
|
+
/**
|
|
61
|
+
* Default headers to be sent with every request.
|
|
62
|
+
* Will be overridden by headers passed to the query.
|
|
63
|
+
* Do not include the `Authorization` header here. Use an `AuthProvider` instead.
|
|
64
|
+
*/
|
|
65
|
+
headers?: RequestHeaders | RequestHeadersMethodMap;
|
|
66
|
+
/**
|
|
67
|
+
* Whether to automatically refresh expired queries when the window regains focus.
|
|
68
|
+
* @default true
|
|
69
|
+
*/
|
|
70
|
+
autoRefreshQueriesOnWindowFocus?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Whether to automatically stop polling queries when the window loses focus.
|
|
73
|
+
* Polling will resume when the window regains focus.
|
|
74
|
+
* @default true
|
|
75
|
+
*/
|
|
76
|
+
enableSmartPolling?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* A retry function to be used for all queries.
|
|
79
|
+
* @default shouldRetryRequest()
|
|
80
|
+
*/
|
|
81
|
+
retryFn?: RequestRetryFn;
|
|
82
|
+
/**
|
|
83
|
+
* Configuration options for all graphql queries.
|
|
84
|
+
*/
|
|
85
|
+
gql?: {
|
|
86
|
+
/**
|
|
87
|
+
* Determines if the query should be sent via GET or POST.
|
|
88
|
+
* - `GET`: The query will be sent via query parameters.
|
|
89
|
+
* - `POST`: The query will be sent via the body.
|
|
90
|
+
* @default 'POST'
|
|
91
|
+
*/
|
|
92
|
+
transferVia?: GqlTransferOption;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Configuration options for all query strings.
|
|
96
|
+
*/
|
|
97
|
+
queryParams?: BuildQueryStringConfig;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
```
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="HttpClient/Queries" />
|
|
4
|
+
|
|
5
|
+
# Queries
|
|
6
|
+
|
|
7
|
+
We use the client to create so-called queries, which we can then use in our components. The client executes the request and offers many convenient features, e.g. to intercept loading or error states or to activate polling on the request.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { def } from '@ethlete/query';
|
|
13
|
+
import { client } from '../fut-api.client';
|
|
14
|
+
|
|
15
|
+
// Interfaces
|
|
16
|
+
interface PostLoginArgs {
|
|
17
|
+
email: string;
|
|
18
|
+
password: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface PostRefreshTokenArgs {
|
|
22
|
+
refreshToken: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface AuthorizationTokenView {
|
|
26
|
+
token: string;
|
|
27
|
+
refreshToken: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Queries
|
|
31
|
+
export const postLogin = client.post({
|
|
32
|
+
route: '/auth/login',
|
|
33
|
+
secure: false,
|
|
34
|
+
types: {
|
|
35
|
+
args: def<PostLoginArgs>(),
|
|
36
|
+
response: def<AuthorizationTokenView>(),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export const postRefreshToken = client.post({
|
|
41
|
+
route: '/auth/refresh-token',
|
|
42
|
+
secure: false,
|
|
43
|
+
types: {
|
|
44
|
+
args: def<PostRefreshTokenArgs>(),
|
|
45
|
+
response: def<AuthorizationTokenView>(),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Options
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
/**
|
|
56
|
+
* The http method to use for the query.
|
|
57
|
+
*/
|
|
58
|
+
method: Method;
|
|
59
|
+
/**
|
|
60
|
+
* Determines if the auth provider should be used for this query.
|
|
61
|
+
* The query **will throw** if the query client's auth provider is unset.
|
|
62
|
+
*/
|
|
63
|
+
secure?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Determines if the query should emit progress events.
|
|
66
|
+
*/
|
|
67
|
+
reportProgress?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Determines the query's response type.
|
|
70
|
+
* @default 'json'
|
|
71
|
+
*/
|
|
72
|
+
responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';
|
|
73
|
+
/**
|
|
74
|
+
* Whether this request should be sent with outgoing credentials (cookies).
|
|
75
|
+
* @default false
|
|
76
|
+
*/
|
|
77
|
+
withCredentials?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Configuration for handling auto refresh triggers.
|
|
80
|
+
*
|
|
81
|
+
* **Note:** This is only available for queries that can be refreshed. (`GET`, `HEAD`, `OPTIONS`, `GQL_QUERY`)
|
|
82
|
+
*/
|
|
83
|
+
autoRefreshOn?: QueryAutoRefreshConfig;
|
|
84
|
+
/**
|
|
85
|
+
* Whether to automatically stop polling for this query when the window loses focus.
|
|
86
|
+
* Polling will resume when the window regains focus.
|
|
87
|
+
*
|
|
88
|
+
* This can only be disabled if `enableSmartPolling` is enabled on the query client.
|
|
89
|
+
* @default true
|
|
90
|
+
*/
|
|
91
|
+
enableSmartPolling?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Object containing the query's type information.
|
|
94
|
+
*/
|
|
95
|
+
types?: {
|
|
96
|
+
/**
|
|
97
|
+
* The type of the successful response.
|
|
98
|
+
*/
|
|
99
|
+
response?: Response;
|
|
100
|
+
/**
|
|
101
|
+
* Arguments for executing the query.
|
|
102
|
+
*
|
|
103
|
+
* - `pathParams`: The path parameters for the query. (in front of the ? in the url)
|
|
104
|
+
* - `queryParams`: The query parameters for the query. (after the ? in the url)
|
|
105
|
+
* - `body`: The body for the query. Unavailable for GET, HEAD and OPTIONS requests.
|
|
106
|
+
* - `headers`: The headers for the query.
|
|
107
|
+
* - `variables`: The variables for the query. (graphql only)
|
|
108
|
+
*/
|
|
109
|
+
args?: Arguments;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Object containing the query's entity store information.
|
|
113
|
+
*/
|
|
114
|
+
entity?: QueryEntityConfig<Store, Data, Response, Arguments, Id>;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HttpStatusCode } from '../request';
|
|
2
|
+
|
|
3
|
+
export interface SymfonyErrorTrace {
|
|
4
|
+
args: string[];
|
|
5
|
+
class: string;
|
|
6
|
+
file: string;
|
|
7
|
+
function: string;
|
|
8
|
+
line: number;
|
|
9
|
+
namespace: string;
|
|
10
|
+
short_class: string;
|
|
11
|
+
type: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SymfonyError {
|
|
15
|
+
class: string;
|
|
16
|
+
detail: string;
|
|
17
|
+
status: HttpStatusCode;
|
|
18
|
+
title: string;
|
|
19
|
+
trace: SymfonyErrorTrace[];
|
|
20
|
+
type: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { FormViolationListView, FormViolationView } from '@ethlete/types';
|
|
2
|
+
import { SymfonyError } from './symfony.types';
|
|
3
|
+
|
|
4
|
+
export const isSymfonyError = (error: unknown): error is SymfonyError => {
|
|
5
|
+
if (!error || typeof error !== 'object') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const symfonyError = error as SymfonyError;
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
symfonyError.class !== undefined &&
|
|
13
|
+
symfonyError.detail !== undefined &&
|
|
14
|
+
symfonyError.status !== undefined &&
|
|
15
|
+
symfonyError.title !== undefined &&
|
|
16
|
+
symfonyError.trace !== undefined &&
|
|
17
|
+
symfonyError.type !== undefined
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const isSymfonyPagerfantaOutOfRangeError = (error: unknown): error is SymfonyError => {
|
|
22
|
+
if (!isSymfonyError(error)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return error.class.startsWith('Pagerfanta') && error.class.endsWith('OutOfRangeCurrentPageException');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const isSymfonyFormViolationListError = (error: unknown): error is FormViolationListView => {
|
|
30
|
+
return typeof error === 'object' && error !== null && 'violations' in error;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const isSymfonyListError = (error: unknown): error is FormViolationView[] => {
|
|
34
|
+
return (
|
|
35
|
+
!!error &&
|
|
36
|
+
typeof error === 'object' &&
|
|
37
|
+
Array.isArray(error) &&
|
|
38
|
+
!!error.length &&
|
|
39
|
+
'message' in error[0] &&
|
|
40
|
+
'propertyPath' in error[0] &&
|
|
41
|
+
'invalidValue' in error[0]
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { CreateComputedOptions, Injector, Signal, assertInInjectionContext, computed, inject } from '@angular/core';
|
|
2
|
+
import { ToObservableOptions, ToSignalOptions, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
3
|
+
import { computedTillTruthy, createDestroy } from '@ethlete/core';
|
|
4
|
+
import { Observable, Subscribable, of, pairwise, startWith, switchMap, takeUntil, tap } from 'rxjs';
|
|
5
|
+
import {
|
|
6
|
+
AnyQuery,
|
|
7
|
+
AnyQueryCollection,
|
|
8
|
+
QueryOf,
|
|
9
|
+
QueryState,
|
|
10
|
+
QueryStateType,
|
|
11
|
+
extractQuery,
|
|
12
|
+
filterQueryStates,
|
|
13
|
+
isQuery,
|
|
14
|
+
isQueryStateFailure,
|
|
15
|
+
isQueryStateLoading,
|
|
16
|
+
isQueryStateSuccess,
|
|
17
|
+
} from '../query';
|
|
18
|
+
import { QueryDataOf } from '../query-creator';
|
|
19
|
+
|
|
20
|
+
export interface QueryContainerConfig {
|
|
21
|
+
/**
|
|
22
|
+
* If `true`, the previous query will be aborted when a new query is pushed into the container.
|
|
23
|
+
* @default true // Only if the request can be cached (GET, OPTIONS, HEAD and GQL_QUERY). Otherwise false.
|
|
24
|
+
*/
|
|
25
|
+
abortPrevious?: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* If `true`, the query will be aborted when the container is destroyed.
|
|
29
|
+
* @default true // Only if the request can be cached (GET, OPTIONS, HEAD and GQL_QUERY). Otherwise false.
|
|
30
|
+
*/
|
|
31
|
+
abortOnDestroy?: boolean;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* If `true`, the previous polling will be stopped when a new query is pushed into the container.
|
|
35
|
+
* @default true // Only if the query has no other dependents and the request can be cached (GET, OPTIONS, HEAD and GQL_QUERY). Otherwise false.
|
|
36
|
+
*/
|
|
37
|
+
stopPreviousPolling?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface QueryFilterConfig {
|
|
41
|
+
/**
|
|
42
|
+
* If `true`, the response will be cached until the next response is received or the query fails.
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
cacheResponse?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const addQueryContainerHandling = (
|
|
49
|
+
obs: Observable<AnyQuery | AnyQuery[] | null>,
|
|
50
|
+
valueFn: () => AnyQuery | AnyQuery[] | null | undefined,
|
|
51
|
+
config?: QueryContainerConfig,
|
|
52
|
+
) => {
|
|
53
|
+
assertInInjectionContext(addQueryContainerHandling);
|
|
54
|
+
|
|
55
|
+
const { abortPrevious, abortOnDestroy, stopPreviousPolling } = config ?? {};
|
|
56
|
+
|
|
57
|
+
const injector = inject(Injector);
|
|
58
|
+
const destroy$ = createDestroy();
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
const tNode = (injector as any)._tNode;
|
|
62
|
+
const componentId = tNode?.index ?? -1;
|
|
63
|
+
|
|
64
|
+
obs
|
|
65
|
+
.pipe(
|
|
66
|
+
takeUntil(destroy$),
|
|
67
|
+
startWith(null),
|
|
68
|
+
pairwise(),
|
|
69
|
+
tap(([prevQuery, currQuery]) => {
|
|
70
|
+
const cleanQuery = (q: AnyQuery | null | undefined) => {
|
|
71
|
+
if (!q?._hasDependents() && ((abortPrevious === undefined && q?.canBeCached) || abortPrevious)) {
|
|
72
|
+
q?.abort();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
!q?._hasDependents() &&
|
|
77
|
+
((stopPreviousPolling === undefined && q?.canBeCached) || stopPreviousPolling) &&
|
|
78
|
+
q?.isPolling
|
|
79
|
+
) {
|
|
80
|
+
q?.stopPolling();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if ((isQuery(prevQuery) || prevQuery === null) && (isQuery(currQuery) || currQuery === null)) {
|
|
85
|
+
prevQuery?._removeDependent(componentId);
|
|
86
|
+
currQuery?._addDependent(componentId);
|
|
87
|
+
|
|
88
|
+
cleanQuery(prevQuery);
|
|
89
|
+
} else if (
|
|
90
|
+
(Array.isArray(prevQuery) || prevQuery === null) &&
|
|
91
|
+
(Array.isArray(currQuery) || currQuery === null)
|
|
92
|
+
) {
|
|
93
|
+
if (prevQuery) {
|
|
94
|
+
for (let i = 0; i < prevQuery.length; i++) {
|
|
95
|
+
prevQuery[i]?._removeDependent(componentId);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (currQuery) {
|
|
100
|
+
for (let i = 0; i < currQuery.length; i++) {
|
|
101
|
+
currQuery[i]?._addDependent(componentId);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (prevQuery) {
|
|
106
|
+
for (let i = 0; i < prevQuery.length; i++) {
|
|
107
|
+
cleanQuery(prevQuery[i]);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} else if (
|
|
111
|
+
(isQuery(prevQuery) && Array.isArray(currQuery)) ||
|
|
112
|
+
(Array.isArray(prevQuery) && isQuery(currQuery))
|
|
113
|
+
) {
|
|
114
|
+
throw new Error('Cannot mix queries and arrays of queries in the same query container.');
|
|
115
|
+
}
|
|
116
|
+
}),
|
|
117
|
+
)
|
|
118
|
+
.subscribe();
|
|
119
|
+
|
|
120
|
+
destroy$.subscribe(() => {
|
|
121
|
+
const query = valueFn();
|
|
122
|
+
|
|
123
|
+
const handleQuery = (q: AnyQuery | null | undefined) => {
|
|
124
|
+
q?._removeDependent(componentId);
|
|
125
|
+
|
|
126
|
+
if (!q?._hasDependents() && ((q?.canBeCached && abortOnDestroy === undefined) || abortOnDestroy)) {
|
|
127
|
+
q?.abort();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (isQuery(query)) {
|
|
132
|
+
handleQuery(query);
|
|
133
|
+
} else if (Array.isArray(query)) {
|
|
134
|
+
for (const q of query) {
|
|
135
|
+
handleQuery(q);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export function toQuerySignal<T extends AnyQuery | null>(
|
|
142
|
+
source: Observable<T> | Subscribable<T>,
|
|
143
|
+
): Signal<T | undefined>;
|
|
144
|
+
export function toQuerySignal<T extends AnyQuery | null>(
|
|
145
|
+
source: Observable<T> | Subscribable<T>,
|
|
146
|
+
options: ToSignalOptions & { initialValue?: undefined; requireSync?: false } & QueryContainerConfig,
|
|
147
|
+
): Signal<T | undefined>;
|
|
148
|
+
export function toQuerySignal<T extends AnyQuery | null>(
|
|
149
|
+
source: Observable<T> | Subscribable<T>,
|
|
150
|
+
options: ToSignalOptions & { initialValue?: null; requireSync?: false } & QueryContainerConfig,
|
|
151
|
+
): Signal<T | null>;
|
|
152
|
+
export function toQuerySignal<T extends AnyQuery | null>(
|
|
153
|
+
source: Observable<T> | Subscribable<T>,
|
|
154
|
+
options: ToSignalOptions & { initialValue?: undefined; requireSync: true } & QueryContainerConfig,
|
|
155
|
+
): Signal<T>;
|
|
156
|
+
export function toQuerySignal<T extends AnyQuery | null, const U extends T>(
|
|
157
|
+
source: Observable<T> | Subscribable<T>,
|
|
158
|
+
options: ToSignalOptions & { initialValue: U; requireSync?: false } & QueryContainerConfig,
|
|
159
|
+
): Signal<T | U>;
|
|
160
|
+
|
|
161
|
+
export function toQuerySignal<T extends AnyQuery | null, U = undefined>(
|
|
162
|
+
source: Observable<T> | Subscribable<T>,
|
|
163
|
+
options?: ToSignalOptions & { initialValue?: U } & QueryContainerConfig,
|
|
164
|
+
): Signal<T | U> {
|
|
165
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
166
|
+
const s = toSignal(source, options as any);
|
|
167
|
+
|
|
168
|
+
addQueryContainerHandling(source as Observable<T>, () => s() as T, options);
|
|
169
|
+
|
|
170
|
+
return s as Signal<T | U>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function queryComputed<T extends AnyQuery | null>(
|
|
174
|
+
computation: () => T,
|
|
175
|
+
options?: CreateComputedOptions<T> & QueryContainerConfig & ToObservableOptions,
|
|
176
|
+
): Signal<T> {
|
|
177
|
+
const c = computed(computation, options);
|
|
178
|
+
const obs = toObservable(c, options);
|
|
179
|
+
|
|
180
|
+
addQueryContainerHandling(obs, () => c(), options);
|
|
181
|
+
|
|
182
|
+
return c;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates a signal that will only be reactive until the first query is created.
|
|
187
|
+
* All subsequent changes inside the computation will be ignored.
|
|
188
|
+
*/
|
|
189
|
+
export function queryComputedTillTruthy<T extends AnyQuery | null>(
|
|
190
|
+
computation: () => T,
|
|
191
|
+
options?: CreateComputedOptions<T> & QueryContainerConfig & ToObservableOptions,
|
|
192
|
+
): Signal<T | null> {
|
|
193
|
+
const c = computedTillTruthy(computed(computation, options));
|
|
194
|
+
const obs = toObservable(c, options);
|
|
195
|
+
|
|
196
|
+
addQueryContainerHandling(obs, () => c(), options);
|
|
197
|
+
|
|
198
|
+
return c;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function queryArrayComputed<T extends AnyQuery[] | null>(
|
|
202
|
+
computation: () => T,
|
|
203
|
+
options?: CreateComputedOptions<T> & QueryContainerConfig & ToObservableOptions,
|
|
204
|
+
): Signal<T> {
|
|
205
|
+
const c = computed(computation, options);
|
|
206
|
+
const obs = toObservable(c, options);
|
|
207
|
+
|
|
208
|
+
addQueryContainerHandling(obs, () => c(), options);
|
|
209
|
+
|
|
210
|
+
return c;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function toQuerySubject<T extends AnyQuery | null>(
|
|
214
|
+
source: Signal<T>,
|
|
215
|
+
options?: ToObservableOptions & QueryContainerConfig,
|
|
216
|
+
): Observable<T> {
|
|
217
|
+
const obs = toObservable(source, options);
|
|
218
|
+
|
|
219
|
+
addQueryContainerHandling(obs, () => source(), options);
|
|
220
|
+
|
|
221
|
+
return obs;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function queryStateSignal<T extends Signal<AnyQuery | AnyQueryCollection | null>>(
|
|
225
|
+
source: T,
|
|
226
|
+
options?: QueryFilterConfig,
|
|
227
|
+
) {
|
|
228
|
+
const { cacheResponse } = options ?? {};
|
|
229
|
+
|
|
230
|
+
return toSignal(
|
|
231
|
+
toObservable(source).pipe(
|
|
232
|
+
switchMap((q) => extractQuery(q)?.state$ ?? of(null)),
|
|
233
|
+
switchMap((state) => {
|
|
234
|
+
if (cacheResponse) {
|
|
235
|
+
return of(state).pipe(
|
|
236
|
+
filterQueryStates([QueryStateType.Success, QueryStateType.Failure, QueryStateType.Cancelled]),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return of(state);
|
|
241
|
+
}),
|
|
242
|
+
),
|
|
243
|
+
{
|
|
244
|
+
initialValue: null,
|
|
245
|
+
},
|
|
246
|
+
) as Signal<QueryState<QueryDataOf<QueryOf<ReturnType<T>>>> | null>;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function queryStateResponseSignal<T extends Signal<AnyQuery | AnyQueryCollection | null>>(
|
|
250
|
+
source: T,
|
|
251
|
+
options?: QueryFilterConfig,
|
|
252
|
+
) {
|
|
253
|
+
const s = queryStateSignal(source, options);
|
|
254
|
+
|
|
255
|
+
return computed(() => {
|
|
256
|
+
const state = s();
|
|
257
|
+
|
|
258
|
+
return isQueryStateSuccess(state) ? state.response : null;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function queryStateErrorSignal<T extends Signal<AnyQuery | AnyQueryCollection | null>>(source: T) {
|
|
263
|
+
const s = queryStateSignal(source);
|
|
264
|
+
|
|
265
|
+
return computed(() => {
|
|
266
|
+
const state = s();
|
|
267
|
+
|
|
268
|
+
return isQueryStateFailure(state) ? state.error : null;
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function queryStateLoadingSignal<T extends Signal<AnyQuery | AnyQueryCollection | null>>(source: T) {
|
|
273
|
+
const s = queryStateSignal(source);
|
|
274
|
+
|
|
275
|
+
return computed(() => {
|
|
276
|
+
const state = s();
|
|
277
|
+
|
|
278
|
+
return isQueryStateLoading(state) ? state : null;
|
|
279
|
+
});
|
|
280
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const deepFreeze = <T extends Record<string, unknown>>(object: T) => {
|
|
2
|
+
// check if object is actually an object or frozen
|
|
3
|
+
if (!object || typeof object !== 'object' || Object.isFrozen(object)) {
|
|
4
|
+
return object;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Retrieve the property names defined on object
|
|
8
|
+
const propNames = Object.getOwnPropertyNames(object);
|
|
9
|
+
|
|
10
|
+
// Freeze properties before freezing self
|
|
11
|
+
|
|
12
|
+
for (const name of propNames) {
|
|
13
|
+
const value = object[name];
|
|
14
|
+
|
|
15
|
+
if (value && typeof value === 'object') {
|
|
16
|
+
deepFreeze(value as T);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return Object.freeze(object);
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest-preset-angular/setup-jest';
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"useDefineForClassFields": false,
|
|
5
|
+
"forceConsistentCasingInFileNames": true,
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noImplicitOverride": true,
|
|
8
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
9
|
+
"noImplicitReturns": true,
|
|
10
|
+
"noFallthroughCasesInSwitch": true
|
|
11
|
+
},
|
|
12
|
+
"files": [],
|
|
13
|
+
"include": [],
|
|
14
|
+
"references": [
|
|
15
|
+
{
|
|
16
|
+
"path": "./tsconfig.lib.json"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "./tsconfig.spec.json"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"extends": "../../tsconfig.base.json",
|
|
23
|
+
"angularCompilerOptions": {
|
|
24
|
+
"enableI18nLegacyMessageIdFormat": false,
|
|
25
|
+
"strictInjectionParameters": true,
|
|
26
|
+
"strictInputAccessModifiers": true,
|
|
27
|
+
"strictTemplates": true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../dist/out-tsc",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"declarationMap": true,
|
|
7
|
+
"inlineSources": true,
|
|
8
|
+
"types": ["mdx"]
|
|
9
|
+
},
|
|
10
|
+
"exclude": ["src/test-setup.ts", "src/**/*.spec.ts", "jest.config.ts", "src/**/*.test.ts"],
|
|
11
|
+
"include": ["src/**/*.ts"]
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../dist/out-tsc",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"types": ["jest", "node"],
|
|
7
|
+
"target": "es2016"
|
|
8
|
+
},
|
|
9
|
+
"files": ["src/test-setup.ts"],
|
|
10
|
+
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
|
|
11
|
+
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generated bundle index. Do not edit.
|
|
3
|
-
*/
|
|
4
|
-
export * from './index';
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRobGV0ZS1xdWVyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYnMvcXVlcnkvc3JjL2V0aGxldGUtcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0=
|
package/esm2022/index.mjs
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export * from './lib/auth';
|
|
2
|
-
export * from './lib/class-validator';
|
|
3
|
-
export * from './lib/devtools/components/query-devtools';
|
|
4
|
-
export * from './lib/devtools/pipes';
|
|
5
|
-
export * from './lib/devtools/utils';
|
|
6
|
-
export * from './lib/directives';
|
|
7
|
-
export * from './lib/entity';
|
|
8
|
-
export * from './lib/gql';
|
|
9
|
-
export * from './lib/infinite-query';
|
|
10
|
-
export * from './lib/logger';
|
|
11
|
-
export * from './lib/query';
|
|
12
|
-
export * from './lib/query-client';
|
|
13
|
-
export * from './lib/query-creator';
|
|
14
|
-
export * from './lib/query-form';
|
|
15
|
-
export * from './lib/query-store';
|
|
16
|
-
export * from './lib/request';
|
|
17
|
-
export * from './lib/symfony';
|
|
18
|
-
export * from './lib/utils';
|
|
19
|
-
// Burst cache
|
|
20
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzL3F1ZXJ5L3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsMENBQTBDLENBQUM7QUFDekQsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsYUFBYSxDQUFDO0FBRTVCLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2xpYi9hdXRoJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NsYXNzLXZhbGlkYXRvcic7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9kZXZ0b29scy9jb21wb25lbnRzL3F1ZXJ5LWRldnRvb2xzJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2RldnRvb2xzL3BpcGVzJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2RldnRvb2xzL3V0aWxzJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2RpcmVjdGl2ZXMnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvZW50aXR5JztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2dxbCc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9pbmZpbml0ZS1xdWVyeSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9sb2dnZXInO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvcXVlcnknO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvcXVlcnktY2xpZW50JztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3F1ZXJ5LWNyZWF0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvcXVlcnktZm9ybSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9xdWVyeS1zdG9yZSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9yZXF1ZXN0JztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3N5bWZvbnknO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvdXRpbHMnO1xuXG4vLyBCdXJzdCBjYWNoZVxuIl19
|